Вход | Регистрация
 
1С:Предприятие :: 1С:Предприятие 8 общая

"Семафоры" на управляемых блокировках

"Семафоры" на управляемых блокировках
Я
   mwide
 
25.01.13 - 15:52
Можно ли с помощью блокировок сделать что-то типа семафора?
Задача такая - есть фрагмент кода, требуется, чтобы он мог выполняться только одним клиентом. Подробнее - есть регистр и константа. В регистр пишутся какие-то данные, константа содержит счетчик записей в регистр. Клиент, который хочет произвести запись, считывает значение константы, пишет в регистр данные, затем меняет значение константы. Нужно, чтобы вся эта операция, от чтения константы и до финальной записи в неё, могла выполняться только одним сеансом. Т.е. если какой-то сеанс собирается начать чтение, он ждал бы, пока другой сеанс не завершит запись.

Попробовал делать так:

блокировка = новый БлокировкаДанных;
элементБлокировки = блокировка.Добавить("Константа.Счетчик");    элементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
блокировка.Заблокировать();
значение = константы.счетчик.получить();

...какие-то действия...

константы.счетчик.установить(значение+1);
блокировка = неопределено;

Проверял параллельную работу на двух сеансах, вставляя перед каждой операцией предупреждение - после того, как один сеанс пройдет через "заблокировать", другой так же может пройти туда, не дожидаясб, пока первый освободит блокировку...

Подскажите, подходит ли вообще механизм управляемых блокировок для решения задачи, и что не так делаю?
 
 
   Fragster
 
1 - 25.01.13 - 15:54
в транзакции?
   mwide
 
2 - 25.01.13 - 15:59
(1) то же самое. Оба сеанса входят в транзакцию. Есть разница, где начинать транзакцию - до блокировки или после?
   hhhh
 
3 - 25.01.13 - 16:11
(2) ну вообще блокировку выбросить если, оставить только транзакцию?
   SUA
 
4 - 25.01.13 - 16:14
процессорного времени жалко?
блокировка + транзакция
   Maxus43
 
5 - 25.01.13 - 16:14
>>константа содержит счетчик записей в регистр
до этого дочитал и всё.
Неправильная реализация имхо
   mwide
 
6 - 25.01.13 - 16:16
(3) на сколько я понимаю, транзакция не означает блокировку данных, а гарантирует только, что данные будут либо записаны все, либо не записано ничего
   mwide
 
7 - 25.01.13 - 16:16
(4) как, например? где нужно начинать транзакцию, до или после блокировки?
   hhhh
 
8 - 25.01.13 - 16:19
(6) нет, неправильно понимаешь. Транзакция не даст второму запустить такую же транзакцию. Он будет ждать.
   mwide
 
9 - 25.01.13 - 16:20
предупреждение("перед начать транзакцию");
начатьТранзакцию(РежимУправленияБлокировкойДанных.Управляемый);    предупреждение("транзакция начата");
    
блокировка = новый БлокировкаДанных;
элементБлокировки = блокировка.Добавить("Константа.Счетчик");    
элементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
предупреждение("перед блокировкой");
блокировка.Заблокировать();
предупреждение("Блокировка выполнена");

В таком варианте, оба сеанса благополучно проходят начало транзакции и потом оба зависают на выполнении блокировки...
   SUA
 
10 - 25.01.13 - 16:22
до
сразу - заблокировать, прочитать/записать, отпустить
РежимБлокировкиДанных (DataLockMode)
Исключительный (Exclusive)
Описание:

Исключительная блокировка не позволит конкурирующему процессу установить разделяемую или исключительную блокировку по этому же условию.

хотя, судя по описанию, должно и по (0) работать
   zmaximka
 
11 - 25.01.13 - 16:24
А режим управления блокировками какой для конфигурации установлен?
   mwide
 
12 - 25.01.13 - 16:25
(10) для конфы в целом - автоматический
   Fragster
 
13 - 25.01.13 - 16:26
(9) убери предупреждение перед блокировкой
   mwide
 
14 - 25.01.13 - 16:26
Попробовал с транзакцией - если один процесс успевает выполнить и открытие транзакции, и блокировку - второй становится в ожидание на открытии транзакции.

Если же первый делает только открытие, второй так же может сделать открытие, и потом оба становятся на блокироке, пока один не решит сообщить о конфликте блокировок
   Fragster
 
15 - 25.01.13 - 16:27
(12) мляяяяяяя.... выбери в запросе "Для изменения" константу твою...
   mwide
 
16 - 25.01.13 - 16:27
(13) что это изменит? предупреждение там для проверки, чтобы контроллировать, кто в каком месте выполняется
   Maxus43
 
17 - 25.01.13 - 16:33
(12) о каких Управляемых блокировках тогда идёт речь то вобще?
   Maxus43
 
18 - 25.01.13 - 16:40
кстати, сменилось же парадигма уже что константы в 1-й строке хранятся в скуле?
   mwide
 
19 - 25.01.13 - 16:44
(17) ошибся, в конфе режим блокировок управляемый
   etc
 
20 - 25.01.13 - 16:44
(18) лень смотреть :)
   mwide
 
21 - 25.01.13 - 16:46
если сделать запрос ДЛЯ ЗАПИСИ, то при одновременном входе в транзакцию двух сеансов, после запроса обращение к константе блокируется в обоих сенасах... (выстрел в голову)
   mwide
 
22 - 25.01.13 - 16:46
в смысле - запрос ДЛЯ ИЗМЕНЕНИЯ
   etc
 
23 - 25.01.13 - 16:47
(0) сделай по другому. При входе в кусок кода пусть пишется строка в регистр "Я Вася Пупкин выпоняю эту процедуру". А при выходе из процедуры очищать. И проверку "Если ТекущийПользователь <> ПользовательИзРегистра ТО ВызватьИсключение("не моё")"
   etc
 
24 - 25.01.13 - 16:48
главное чтобы сеансы не падали :)
   Bober
 
25 - 25.01.13 - 16:52
(0) если нужен счетчик и "хитрая" блокировка, то сделай служебный план обмена и блокируй узел. Фишка в том, что блокировать узел можно без транзакции и там есть встроенный счетчик
   zmaximka
 
26 - 25.01.13 - 16:57
А у самой константы режим управления какой?
   zmaximka
 
27 - 25.01.13 - 16:57
В смысле режим управления блокировками
   mwide
 
28 - 25.01.13 - 17:03
(27) у константы режим управляемый
   Reset
 
29 - 25.01.13 - 17:06
(26) А какое это имеет значение в свете (12)? :)
   zmaximka
 
30 - 25.01.13 - 17:06
По идее код из (0) должен работать
 
 
   Maxus43
 
31 - 25.01.13 - 17:07
(29) > (19) автор не определился ещё)
   Bober
 
32 - 25.01.13 - 17:08
(0) даже еще веселее, сделай план обман  семаформы и моргай сколько хочется
   Reset
 
33 - 25.01.13 - 17:16
(31)(27) аа, сорри. По диагонали тему просмотрел.
   mwide
 
34 - 25.01.13 - 17:17
(32) всё классно, только сеанс на ожидание не становится... если только обработать исключение и крутиться в цикле, пока не получится заблокировать... Наверное, если с блокировками не получится, сделаю так, спасибо за идею :) хотя с жесть, конечно :)
   Bober
 
35 - 25.01.13 - 17:20
(34) так тоже самое у тебя с блокировками будет, только ожидание на блокировку будет идти дольше (от 40 сек). А тут сразу да или нет.
   Reset
 
36 - 25.01.13 - 17:21
Попробовал (9), правда без кучи этих предупреждений (достаточно одного перед завершением транзакции) - все работает.
   Reset
 
37 - 25.01.13 - 17:22
(34) разберись с блокировками, пригодится ;)
   mwide
 
38 - 25.01.13 - 17:24
(37) как ты без предупреждений контролируешь, в каком месте какой сеанс выполняется?
   Reset
 
39 - 25.01.13 - 17:47
(38) цитата:
"(достаточно одного перед завершением транзакции)"
   Живой Ископаемый
40 - 25.01.13 - 20:07
(18) сменилась в 14релизе
   Torquader
 
41 - 26.01.13 - 01:43
Открытие транзакции на самом деле никакой блокировки не вызывает - оно сообщает серверу, что нужно изменить режим отслеживания изменений. То есть после НачатьТранзакцию() система продолжит исполнение кода до первого обращения к данным - если сначала будет произведено чтение, а потом запись, то две транзакции "столкнуться", то есть заблокируют друг друга. После этого сервер каким-то случайным образом "принесёт одну в жертву".
Можно, конечно, сделать запись в какую-то таблицу текущего времени, чтобы гарантировано всех заблокировать, а уже после этого продолжить.
Если есть общая директория, то можно использовать открытие файла на запись - только один процесс его сможет открыть, но в серверной версии 1С общая директория может быть только на сервере.
   mwide
 
42 - 29.01.13 - 10:45
(41) спасибо, идея с записью работает. Остановился на таком варианте:
Завести отдельную константу под семафор, перед началом доступа к критическому ресурсу открывать транзакцию и пытаться в неё писать. Тогда сеанс, который первый произел запись, получает управление, остальные ждут, пока он не закроет транзакцию.

Собственно задача была такая - сеанс читает значение счетчика из константы, наращивает его и записывает обратно. Нужно не дать двум сеансом прочитать одно и то же значение. То есть, если первый уже начал читать, то второй не читает, пока первый не запишет.
   Torquader
 
43 - 01.02.13 - 02:45
(42) Вообще-то, в нормальных системах это называется AddCounter, то есть увеличение счётчика, которое должно делаться прозрачно в транзакциях - и есть специальные объекты "генераторы" в SQK-системах, только вот 1С до этого ещё не доросла.
   France
 
44 - 01.02.13 - 02:53
Почему не доросла? А нумерация\кодирование объектов? Чего и автору желаю
   Torquader
 
45 - 04.02.13 - 01:03
(44) Нумерация сделана встроенными средствами - и, надо сказать, даже работает, но использовать её без объекта невозможно.
Вы ещё генерацию GUID вспомните - она там тоже есть только потому, что объекты по GUID идентифицируются.
   mistеr
 
46 - 04.02.13 - 01:22
(42) А можно исходную бизнес-задачу? Чисто поржать над архитектурной композицией в целом.
   France
 
47 - 04.02.13 - 08:36
(45) не касаясь исходной задачи: что мешает создать справочник "Автонумерация" и создавать так нужные автору уникальные и контролируемые номера?
   Torquader
 
48 - 05.02.13 - 02:50
(47) На самом деле, проблема автонумерации нерешаема в общем случае. Конечно, если мы последовательно что-то нумеруем, то нужно только запретить параллельное исполнение кода, чтобы не было двух одинаковых номеров. Но, как только с системой начинают работать пользователи, начинаются сюрпризы - например - кто-то получил номер, а потом удалил пронумерованный объект - в нумерации получается дырка. Конечно, при желании её можно отловить и заполнить, но тогда нарушится последовательность объектов, так как позднее созданный будет иметь меньший номер.
1С прекрасно нумерует в момент сохранения, но никто не застрахован от того, что пронумерованный объект не будет удалён.
   МуМу
 
49 - 05.02.13 - 05:54
(48) Нормально все решается, вопрос только как задачу ставить. Например можно в "дырки " ставить новые элементы, по диапазону номерации.
   0xFFFFFF
 
50 - 05.02.13 - 07:05
(41) че так сложно то? Стандартный механизм блокировок уже неработает чтоли?
   tuxik07
 
51 - 05.02.13 - 08:22
а разве Блокировка.Заблокировать() не работает уже?


Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Тема не обновлялась длительное время, и была помечена как архивная. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.