gifts2017

Мьютексы в 1С 7.7

Опубликовал Sk0rp (Sk0rp) в раздел Обмен - Обмен через DBF

Существует ряд задач, которые требуют строго последовательного исполнения. Чаще всего это возникает при многопоточном программировании, в этом случае используются критические секции, но иногда надо синхронизировать и разные приложения - для этого существуют такие объекты ядра операционной системы как Мьютекс-ы. http://ru.wikipedia.org/wiki/Мьютекс
В статье рассказывается как можно сделать аналогичный объект средствами 1С v7.7

Существует ряд задач, которые требуют строго последовательного исполнения. Чаще всего это возникает при многопоточном программировании, в этом случае используются критические секции, но иногда надо синхронизировать и разные приложения - для этого в существуют такие объекты ядра операционной системы как Мьютекс-ы.

В википедии есть подробная статья про них, если кому интересно: http://ru.wikipedia.org/wiki/Мьютекс

Для чего это может понадобится в 1С ?

Например вы хотите, что бы при входе в систему любого пользователя выполнялось какое-либо действие (загрузка/выгрузка файла обмена, загрузка валют, запуск построения статистики при первом входе за день и т.д.) или вам просто очень бы не хотелось, что бы два пользователя одновременно запустили одну и ту же обработку (например обмен с сайтом), т.к. результат одновременной обработки из двух мест непредсказуем.

Отсюда вытекает задача объекта синхронизации, владеть которым в момент времени мог бы только один сеанс. Я предлагаю для этого обходится стандартными возможностями 7.7

Полное описание к задаче:

  • Должен быть объект который монопольно можно захватить из 1С.
  • Обращаться к объекту должно быть можно их разных запущенных сеансов, разных компьютеров, в идеале разных ИБ
  • При аварийном завершении сеанса захватившего объект - захват должен сниматься, что бы не оказалось подвисших блокировок.

 

Из описания стало понятно, что это должен быть файл на который получен эксклюзивный доступ - в этом случае его никто другой не сможет открыть даже для чтения. Это удобно тем, что при падении 1С - винда сама отследит, что владельца файла больше нет и снимет с файла блокировку.

Таким свойством обладает открытый через XBase файл dbf. На этом и построен алгоритм.

Всего работа с синхронизацией состоит в данном случае из 2х функций: Lock() и UnLock(): первая пытается захватить объект и если это получается - возвращает (1), если не получается по каким - либо причинам - возвращает (0) и тут уже делайте, что хотите: завершайте работу или в цикле пробуйте получить объект себе во владение, как угодно. Снятие блокировки происходит при вызове UnLock() или при завершении обработки (разрушении объекта XBase).

//Ж*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖSЖЖPЖЖ*ЖЖ*Ж

Перем ФайлСинхронизации, ИмяФайлаСинхронизации;

//Ж*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖSЖЖPЖЖ*ЖЖ*Ж

Функция Lock()
    Если ПустоеЗначение(ФайлСинхронизации) = 0 Тогда
        //Трас("Объект блокировки уже создан");
        Возврат 1;
    КонецЕсли;

    Попытка

        ФайлСинхронизации = СоздатьОбъект("XBase");
        ФайлСинхронизации.КодоваяСтраница(1);
        ФайлСинхронизации.ДобавитьПоле("Name","S", 64, 0);
        ФайлСинхронизации.СоздатьФайл(ИмяФайлаСинхронизации);
        ФайлСинхронизации.Добавить();
        ФайлСинхронизации.Name = ИмяПользователя();
        ФайлСинхронизации.Записать();
        ФайлСинхронизации.ЗакрытьФайл();

        Если ФС.СуществуетФайл(ИмяФайлаСинхронизации) = 1 Тогда

            ФайлСинхронизации.ОткрытьФайл(ИмяФайлаСинхронизации);

            Если ФайлСинхронизации.Первая() = 1 Тогда
                Если НРег(СокрЛП(ФайлСинхронизации.Name)) = НРег(СокрЛП(ИмяПользователя())) Тогда
                    Возврат 1;
                Иначе
                    //Трас("Не удалось получить блокировку, файл перехватил: " + ФайлСинхронизации.Name, "!");
                КонецЕсли;
            Иначе
                //Трас("Не удалось спозиционироваться в файле блокировки", "!");
            КонецЕсли;
            ФайлСинхронизации.ЗакрытьФайл();
        Иначе
            //Трас("Не удалось создать файл блокировки", "!");
        КонецЕсли;

    Исключение
        //Трас("Исключение при блокировке: " + ОписаниеОшибки(), "!");
    КонецПопытки;

    //Трас("Очищен объект блокировки (после неудачной попытки захвата)");
    ФайлСинхронизации = ПолучитьПустоеЗначение();
    Возврат 0;
КонецФункции

//Ж*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖSЖЖPЖЖ*ЖЖ*Ж
Процедура UnLock()
    Если ПустоеЗначение(ФайлСинхронизации) = 1 Тогда
        //Трас("Объект блокировки не был создан");
    КонецЕсли;

    Попытка
        ФайлСинхронизации.ЗакрытьФайл();
    Исключение
        //Трас("Исключение при снятии блокировки: " + ОписаниеОшибки(), "!");
    КонецПопытки;

    //Трас("Очищен объект блокировки");
    ФайлСинхронизации = ПолучитьПустоеЗначение();
КонецПроцедуры

Перед первым вызовом началом работы надо задать полное имя для файла, который будет объектом синхронизации в ИмяФайлаСинхронизации.

 

Удачного кодинга!

 

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Александр Рытов (Арчибальд) 05.07.10 08:49
Кто бы мог 35 лет назад подумать, что семафоры Дейкстры обзовут этаким словом :o
2. Игорь Исхаков (Ish_2) 05.07.10 10:22
Я про семафоры именно Дейкстры не помню или не знаю.
Зачем смущаешь публику ? Рисуешься ?
3. Sk0rp (Sk0rp) 05.07.10 10:44
(1) Это частный случай семафора, согласен :) А вот про Дейкстру не слышал :(
4. Александр Рытов (Арчибальд) 05.07.10 10:47
(2) Отрицающий прошлое не имеет будущего ©
Известность Дейкстре принесли его работы в области применения математической логики при разработке компьютерных программ. Он активно участвовал в разработке языка программирования Алгол и написал первый компилятор Алгол-60. Будучи одним из авторов концепции структурного программирования, он «проповедовал» отказ от использования инструкции GOTO. Также ему принадлежит идея применения «семафоров» для синхронизации процессов в многозадачных системах и алгоритм нахождения кратчайшего пути на ориентированном графе с неотрицательными весами рёбер, известный как Алгоритм Дейкстры. В 1972 году Дейкстра стал лауреатом премии Тьюринга.
Когда советское правительство приняло решение о переходе советской промышленности к копированию модельного ряда IBM/360, Дейкстра (работавший в то время в конкурировавшей с IBM фирме Burroughs) назвал это решение величайшей победой Запада в холодной войне, а выбранную для клонирования модель IBM/360 (прообраз советской ЕС ЭВМ) — величайшей диверсией Запада против СССР.
5. Александр Рытов (Арчибальд) 05.07.10 11:12
В первом посте ошибочка :oops: не 35, а 45
6. Вячеслав Кадацкий (marsohod) 07.07.10 11:09
Еще один вариант.
Возможно, вы замечали, что если документ или элемент справочника открыт одним пользователем, то при попытке открыть его другим пользователем 1С выдает предупреждение о том, что запись заблокирована. На знании этого факта можно предложить другой вариант реализации.
Создаем новый справочник "Блокировки" с одним-единственным элементом и при начале некоторых действий, которые требуют указанных условий пытаемся его открыть. Если удалось - значит все в порядке. Если нет, тогда отказ.
Или (как подвариант) - все указанное делается в существующем справочнике или создается своего рода "предопределенный" документ.
7. Вячеслав Кадацкий (marsohod) 07.07.10 11:12
+6
Уточню: подразумевается не получение ссылки на объект, а использование функции ОткрытьФорму()
8. Вячеслав Кадацкий (marsohod) 07.07.10 11:29
+6 +7
Строго говоря предложенный вариант уже не подпадает под определение мьютекса :)
это скорее "критическая секция" :)
9. Sk0rp (Sk0rp) 07.07.10 12:48
(6)(7)(8) Как один из вариантов возможен для рассмотрения. Мне он не понравился тем, что
1. при некорректном завершении обработки, которая открыла форму - форма так и останется открытой.
2. это действительно ближе к критической секции, поскольку не получится расширить на разные базы.
3. не хочется ради этого менять структуру базы, а использовать "предопределенный" элемент чревато тем, что он на самом деле может понадобится :)
4. открытую форму запросто могут закрыть вручную, да и не красиво, когда что-то мелькает :)
10. Александр Рытов (Арчибальд) 07.07.10 12:59
(9) Эти все заморочки легко разруливаются Мираклем от Абадонны 8-)
11. Вячеслав Кадацкий (marsohod) 07.07.10 14:02
(9) именно из-за п.2 "...не получится расширить на разные базы..." этот вариант и следует относить к критической секции :)
Остальное... в общем-то решаемо, как подметил Арчибальд.
12. Александр Рытов (Арчибальд) 07.07.10 14:18
13. Sk0rp (Sk0rp) 07.07.10 15:14
(12) Как всякая теория мало применима на практике или ОЧЕНЬ сильно устарела. Там не раскрывается понятие атомарности операций, без которого комбинации действий вида: проверить, если больше нуля уменьшить - рассматриваются как разные действия, а это прямой путь большим проблемам.
На практике даже инкремент переменной может дать очень неожиданный результат если не прикладывать специальных усилий для этого.
А современная рабочая теория это: lockfree programming.
14. bulpi bulpi (bulpi) 07.07.10 16:18
"при падении 1С - винда сама отследит, что владельца файла больше нет и снимет с файла блокировку"
Самая хитрая ложь - это полуправда ;) Правильно написАть : Винда ДОЛЖНА сама отследить... Но не делает ни фига довольно часто. Приходится вручную снимать блокировку Unlocker -ом
15. Sk0rp (Sk0rp) 07.07.10 16:33
(14) В целом согласен, хотя же это чаще случается если процесс в памяти зависнет. Такое иногда с некоторыми программами случается. С 1С у меня еще не было. А если такое случится с 1С, то там ИМХО проблемы будут посерьезнее, :) т.к. 1С-ка сама любит использовать прием с флаговыми файлами.
16. Александр Рытов (Арчибальд) 08.07.10 07:26
(13) Не согласен. Во-первых, семафоры именно тем и отличаются от обычных целочисленных переменных, что указанная комбинация действий атомарна. А во-вторых, аппаратная реализация "один в один" этих семафоров - это именно то, что позволило создать суперкомпьютеры (начиная с CRAY), и до сих пор успешно используется.
17. Sk0rp (Sk0rp) 08.07.10 10:51
(16) Семафор Дейкстры - это скорее парадигма, чем конкретная реализация - это видно из его трудов. Это безусловно определило современные представления об объектах синхронизации, но с тех пор его идеи сильно эволюционировали.
18. Oleksandr Tretiak (alur) 12.07.10 15:04
Штатный метод "Блокировка()" гораздо проще, наглядней и надежней.
19. Александр Рытов (Арчибальд) 12.07.10 15:16
(18) Штатные методы работают в одной базе.
20. Sk0rp (Sk0rp) 12.07.10 16:09
(18) А какой объект блокировать?
21. Александр Рытов (Арчибальд) 12.07.10 16:14
(20) Это-то понятно. Завести специальный справочник - получится массив двоичных семафоров...
22. Oleksandr Tretiak (alur) 12.07.10 17:14
Ну для нескольких баз можно завести отдельную "блокировочную" базу "семафоров" и поднимать ее отовсюду через COM :D
23. Sk0rp (Sk0rp) 12.07.10 17:33
(22) Тогда чего бы SQL не поставить и в нем записи не лочить? :)
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа