История изменений
Исправление byko3y, (текущая версия) :
Вопрос: возможно ли вместо рестарта транзакции в младшем потоке использовать умные локи, которые блокируют младший поток, когда он дошёл до любого из данных, которое будет использоваться в начавшейся транзакции старшего?
Это поднимает проблему избегания дедлоков, которую я не описал в статье, поскольку это много унылых технических деталей, над которыми я в свое время поломал голову.
Теоретически, описанное тобой можно сделать, и это была первая модель, которую я хотел реализовать. У меня возникли проблемы даже на уровне простых блокировок (эксклюзивная блокировка на любой доступ, чтение или запись), поскольку для проверки отсутствия дедлока нужно проходить по всей цепочке ожиданий потоков, которая, к тому же, не стоит на месте, потому проверять ее нужно снова и снова. В итоге я так и не отладил систему с проверкой дедлоков, переделав блокировки на RW, где проверка цепочки зависимостей блокировок и вовсе является гиблым делом.
Конечно, проще было бы что-то проверять, если бы требуемые блокировки объявлялись на старте транзакции. Я даже где-то находил статью с теоретическим описанием именно такой системы. Но для питона, как написано в статье из исходного сообщения, практически невозможно определить требуемые блокировки заранее в общем случае.
По этой причине, как я описывал еще год назад, я могу быть уверенным только в одном уровне зависимостей, то есть, выполняемых беспрепятственно транзакциях и тех, кто непосредственно их ждет. Ждать ждущих уже нельзя. Выполняемые беспрепятственно — это те, кто уже имеет блокировки и не имеет конфликтов с другими блокировками. Как правило, это просто самая старая транзакция.
Год назад я думал прямо-таки наделять их статусом «беспрепятственно выполняющаяся» и «ждущая», но потому покрутил-повертел, и решил, что проще реализовать фактически ту же работу, если брать блокировку по принципу «самый старый берет блокировку, все остальные прерывают транзакцию и ждут освобождения блокировки» — то есть, как нарисовано на блок-схеме. Ожидание по сигналу применяется только для старой транзакции, которая ждет, пока молодняк освободит блокировку (или придет более старшая транзакция) — эта деталь на блок-схеме не отображена.
Как видишь, даже в самых простых раскладах это такой вынос мозга, что большинство софтописак решают просто «ну его нафик», и делают lazy транзакции или прерывание дедлока по таймауту.
Исходная версия byko3y, :
Вопрос: возможно ли вместо рестарта транзакции в младшем потоке использовать умные локи, которые блокируют младший поток, когда он дошёл до любого из данных, которое будет использоваться в начавшейся транзакции старшего?
Это поднимает проблему избегания дедлоков, которую я не описал в статье, поскольку это много унылых технических деталей, над которыми я в свое время поломал голову.
Теоретически, описанное тобой можно сделать, и это была первая модель, которую я хотел реализовать. У меня возникли проблемы даже на уровне простых блокировок (эксклюзивная блоокировка на любой доступ, чтение или запись), поскольку для проверки отсутствия дедлока нужно проходить по всей цепочке ожиданий потоков, которая, к тому же, не стоит на месте, потому проверять ее нужно снова и снова. В итоге я так и не отладил систему с проверкой дедлоков, переделав блокировки на RW, где проверка цепочки зависимостей блокировок и вовсе является гиблым делом.
Конечно, проще было бы что-то проверять, если бы требуемые блокировки объявлялись на старте. Я даже где-то находил статью именно с такой системой. Но для питона, как написано в статье, практически невозможно определить требуемые блокировки заранее в общем случае.
По этой причине, как я описывал еще год назад, я могу быть уверенным только в одном уровне зависимостей, то есть, выполняемых беспрепятственно транзакциях и те, кто их ждет. Ждать ждущих уже нельзя. Выполняемые беспрепятственно — это те, кто уже имеет блокировки и не имеет конфликтов с другими блокировками. Как правило, это просто самая старая транзакция.
Год назад я думал прямо-таки наделять их статусом «беспрепятственно выполняющаяся» и «ждущая», но потому покрутил-повертел, и решил, что проще реализовать фактически ту же работу, если брать блокировку по принципу «самый старый берет блокировку, все остальные прерывают транзакцию и ждут освобождения блокировки» — то есть, как нарисовано на блок-схеме. Ожидание по сигналу применяется только для старой транзакции, которая ждет, пока молодняк освободит блокировку (или придет более старшая транзакция) — эта деталь на блок-схеме не отображена.
Как видишь, даже в самых простых раскладах это такой вынос мозга, что большинство софтописак решают просто «ну его нафик», и делают lazy транзакции или прерывание дедлока по таймауту.