|
|||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||
|
Вирішення
проблеми: синхронізація
У попередній
програмі виникає ситуація,
коли результат роботи програми
залежить від порядку виконання
потоків. Щоб позбавитися від неї,
необхідно переконатися в тому, що
команди типу If mhouse.HouseTemp
< mhouse.MAX_TEMP - 5 Then...
повністю відпрацьовуються активним потоком
до того, як він буде перерваний.
Ця властивість називається
атомарностид — блок коди повинен
виконуватися кожним потоком без переривання,
як атомарна одиниця. Група
команд, об'єднаних в атомарний блок,
не може бути перервана
планувальником потоків до її завершення. У
будь-якій багатопотоковій
мові програмування існують
свої способи забезпечення атомарності.
У VB .NET найпростіше скористатися
командою Synclock, при виклику якої
передається об'єктна змінна.
Внесіть до процедури Changetemperature з
попереднього прикладу невеликі
зміни, і програма запрацює
нормально: Private Sub
Changetemperature() Synclock (mhouse) Try If mhouse.HouseTemp < mhouse.MAXJTEMP -5 Then Thread.Sleep(200) mhouse.HouseTemp += 5 Console.WriteLine("Am
in " & Me.mName & _ ".Current temperature is " & mhouse.HouseTemp) Elself mhouse.HouseTemp < mhouse. Max_temp Then Thread.Sleep(200)
mhouse.HouseTemp += 1 Console.WriteLine("Am
in " & Me.mName &_ ".Current temperature is
" & mhouse.HomeTemp) Else Console.WriteLineC'Am
in " & Me.mName & _ ".Current temperature is
" & mhouse.HouseTemp) ' Нічого не робити, температура нормальна End If
Catch tie As Threadlnterruptedexception '
Пасивне очікування було перерване Catch e As Exception ' Інші виключення End Try End Synclock End Sub Код блоку Synclock виконується
атомарно. Доступ до нього з
боку решти всіх потоків буде
закритий, поки перший потік не зніме
блокування командою End Synclock. Якщо
потік в блоці, що
синхронізується, переходить в стан
пасивного очікування, блокування
зберігається аж до переривання
або відновлення роботи потоку.
Залишається згадати
про те, що за допомогою команди
Synclock легко реалізуються умовні
змінні. Для цього потрібно
буде лише синхронізувати
запис в загальну логічну властивість,
доступну для читання і запису, як
це зроблено в наступному фрагменті: Public
Class Conditionvariable Private Shared locker As Object= New Object() Private Shared mok As Boolean Shared Property Theconditionvariable()As Boolean Get Return mok End
Get Set(Byval Value As
Boolean) Synclock (locker) mok= Value End Synclock End Set End Property End Class
Команда
Synclock і клас Monitor
Використання команди Synclock
пов'язане з деякими тонкощами, що
не виявилися в приведених
вище простих прикладах. Так,
дуже важливу роль грає вибір об'єкту
синхронізації. Спробуйте запустити
попередню програму з командою
Synclock(Me) замість Synclock(mhouse). Температура
знову піднімається вище за
порогову величину! Пам'ятаєте,
що команда Synclock
проводить синхронізацію по об'єкту,
переданому як параметр, а не по
фрагменту коди. Параметр Synclock
грає роль дверей для звернення до
фрагмента, що синхронізується,
з інших потоків. Команда
Synclock(Me) фактично відкриває
декілька різних «дверей», адже саме
цього ви і намагалися уникнути за
допомогою синхронізації. Мораль: Для захисту
загальних даних в багатопотоковому
застосуванні команда Synclock повинна
синхронізуватися по одному
об'єкту.
Оскільки синхронізація пов'язана з
конкретним об'єктом, в деяких
ситуаціях можливе
ненавмисне блокування інших
фрагментів. Допустимо, у вас є
два синхронізовані методи first
і second, причому обидва
методи синхронізуються по об'єкту
biglock. Коли потік 1 входить в метод first
і захоплює biglock, жоден потік не
зможе увійти до методу second, тому що
доступ до нього вже обмежений потоком
1! Функціональність
команди Synclock можна розглядати
як підмножина функціональності
класу Monitor. Клас Monitor володіє
розширеними можливостями
налаштування, і з його допомогою можна
вирішувати нетривіальні завдання
синхронізації. Команда Synclock
є наближеним аналогом
методів Enter і Exi t класу Moni tor: Try Monitor.Enter(theobject)
Finally Monitor.Exit(theobject) End Try
|
|
|||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||