Хардуерна взаимна поддръжка

Наличието на хардуерна поддръжка за взаимно изключване ви позволява да опростите алгоритмите и да увеличите тяхната ефективност по същия начин, както се случва в други области на програмирането. Вече споменахме конвенционалния хардуер за решаване на проблема с прилагането на взаимни изключения, когато говорихме за използването на механизма за дезактивиране/разрешаване на прекъсване.

Много изчислителни системи също имат специални процесорни инструкции, които ви позволяват да проверявате и променяте стойността на машинна дума или да разменяте стойностите на две машинни думи в паметта, изпълнявайки тези действия като атомарни операции. Нека обсъдим как концепциите на такива команди могат да се използват за реализиране на взаимно изключване.

Команда тестване и задаване

Изпълнението на команда Test-and-Set, която проверява стойността на булева променлива, докато задава нейната стойност на 1, може да се разглежда като изпълнение на функция

int Test_and_Set (int *target)

int tmp = *target; *цел = 1; върни tmp;

С тази атомарна команда можем да модифицираме нашия алгоритъм за променливата за заключване, за да осигурим взаимно изключване.

споделено int lock = 0;

докато (някое условие)

while(Test_and_Set(&lock));

Критичен раздел

заключване = 0;

Останалата секция

Команда за размяна

Изпълнението на командата Swap, която разменя две стойности в паметта, може да се илюстрира със следната функция

недействителна размяна (int *a, int *b)

int tmp = *a; *a = *b; *b = tmp;

Използвайки командата atomic Swap, можем да приложим предишния алгоритъм чрез въвеждане на допълнителен булев променлив ключлокално за всеки процес:

споделено int lock = 0; ключ int;

докато (някое условие)

ключ = 1; направете размяна (&заключване,&ключ); while(клавиш);

Критичен раздел

заключване = 0;

Останалата секция

Глава 6 Механизми за синхронизиране

Въпреки че алгоритмите, разгледани в края на предишната глава, са правилни, те са доста тромави и им липсва елегантност. Освен това процедурата на изчакване за влизане в критичен регион включва въртене на процеса за доста дълго време в празен цикъл, като лениво поглъща ценно процесорно време. Има и други сериозни недостатъци в алгоритмите, изградени с помощта на конвенционалните езици за програмиране. Да приемем, че в изчислителната система има два взаимодействащи процеса: единият от тях -H - с висок приоритет, другият -L - с нисък приоритет. Нека планировчикът да бъде настроен така, че процес с висок приоритет да изпреварва процес с нисък приоритет, когато е готов за изпълнение, и да заема процесора за времетраенето на неговия CPU пакет (освен ако не се появи процес с по-висок приоритет). Тогава в случай, че процесътL е в своята критична секция, а процесътH, след като е получил процесора, се е приближил до входа на критичната област, получаваме задънена улица. ПроцесътH не може да влезе в критичната област, докато е в цикъл, и на процесL не се дава контрол да напусне критичната област.

За да се преодолеят тези проблеми, са разработени различни механизми за синхронизация от по-високо ниво: семафори, монитори и съобщения, които са темите на тази глава.

Семафори

Един от първите механизми, предложени за синхронизацияповедението на процесите се превърна в семафори, чиято концепция е описана от Дейкстра през 1965 г.

Концепцията за семафори

Семафорът е целочислена променлива, която приема неотрицателни стойности и може да бъде достъпна от всеки процес, освен в момента на инициализацията му, само чрез две атомарни операции:P (от датската дума proberen - проверявам) иV (от verhogen - увеличавам). Класическата дефиниция на тези операции е следната:

P(S):чао С