"Здравей, Амиго! Имаме панацея - лек за всички болести. Както вече видяхме, неконтролираното превключване на нишки е проблем."
"Защо самите нишки не могат да решат кога да превключат към следващата нишка? Направете всичко необходимо и след това сигнализирайте, «Готово!"?"
„Позволяването на самите нишки да контролират превключването би било още по-голям проблем. Да предположим, че имате няHowъв зле написан code и нишката никога не предава процесора. Навремето това работеше така. И беше истински кошмар.“
"Добре. И така, Howво е решението?"
" Блокиране на други теми. Ето How работи."
Стана ясно, че нишките се намесват една в друга, когато се опитват да използват споделени обекти и/or ресурси . Точно Howто видяхме в примера с конзолен изход: има една конзола и всички нишки, извеждани към нея. Разхвърляно е.
Така беше изобретен специален обект: мютексът . Това е като табела на вратата на банята, която казва „свободно / заето“ . Има две състояния: обектът е наличен or зает . Тези състояния се наричат още «заключени» и «отключени».
Когато дадена нишка се нуждае от обект, споделен с други нишки, тя проверява мютекса, свързан с обекта. Ако мютексът е отключен, тогава нишката го заключва (маркира го като «зает») и започва да използва споделения ресурс. След като нишката свърши работата си, мютексът се отключва (маркиран като «достъпен»).
Ако нишката иска да използва обекта и мутексът е заключен, тогава нишката заспива, докато чака. Когато мутексът най-накрая бъде отключен от заемащата нишка, нашата нишка веднага ще я заключи и ще започне да работи. Аналогията с табела на вратата на банята е перфектна.
"И така, How да работя с mutex? Трябва ли да създавам специални обекти?"
„Много по-просто е от това. Създателите на Java са вградor този мютекс в класа Object. Така че дори не е нужно да го създавате. Той е част от всеки обект. Ето How работи всичко:“
Код | Описание |
---|---|
|
Методът swap разменя стойностите на променливите name1 и name2.
Какво може да се случи, ако бъде извикан от две нишки едновременно? |
Действително изпълнение на codeа | Код на първата нишка | Код на втората нишка |
---|---|---|
|
|
|
Долния ред |
---|
Стойностите на променливите бяха разменени два пъти, връщайки се на първоначалните им места. |
Обърнете внимание на ключовата дума synchronized .
"Да, Howво означава това?"
„Когато нишка влезе в блок от code, маркиран като синхронизиран, Java машината незабавно заключва мютекса на обекта, посочен в скоби след думата синхронизиран. Никоя друга нишка не може да влезе в този блок, докато нашата нишка не го напусне. Веднага щом нашата нишка напусне блокът е маркиран като синхронизиран, мютексът незабавно и автоматично се отключва и ще бъде достъпен за придобиване от друга нишка."
Ако мютексът е зает, нашата нишка ще стои неподвижна и ще чака да се освободи.
„Толкова просто и толкова елегантно. Това е красиво решение.“
"Да. Но Howво мислите, че ще се случи в този случай?"
Код | Описание |
---|---|
|
Методите swap и swap2 споделят един и същ mutex ( този обект). |
Какво се случва, ако една нишка извика метода swap, а друга нишка извика метода swap2?
„Тъй като mutex е същият, втората нишка ще трябва да изчака, докато първата нишка напусне синхронизирания блок. Така че няма да има проблеми с едновременния достъп.“
"Браво, Амиго! Това е верният отговор!"
Сега бих искал да отбележа, че synchronized може да се използва за маркиране не само на блокове от code, но и на методи. Ето Howво означава това:
Код | Какво наистина се случва |
---|---|
|
|
GO TO FULL VERSION