Вход | Регистрация


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
а разве Блокировка.Заблокировать() не работает уже?


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