Хардуерна взаимна поддръжка
Наличието на хардуерна поддръжка за взаимно изключване ви позволява да опростите алгоритмите и да увеличите тяхната ефективност по същия начин, както се случва в други области на програмирането. Вече споменахме конвенционалния хардуер за решаване на проблема с прилагането на взаимни изключения, когато говорихме за използването на механизма за дезактивиране/разрешаване на прекъсване.
Много изчислителни системи също имат специални процесорни инструкции, които ви позволяват да проверявате и променяте стойността на машинна дума или да разменяте стойностите на две машинни думи в паметта, изпълнявайки тези действия като атомарни операции. Нека обсъдим как концепциите на такива команди могат да се използват за реализиране на взаимно изключване.
Команда тестване и задаване
Изпълнението на команда 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): | чао С |