Конкурентно Програмиране

16
Конкурентно програмиране 2005 1 Конкурентно Програмиране Семафори: използване за решаване на основни синхронизационни проблеми

Upload: kaya

Post on 04-Jan-2016

203 views

Category:

Documents


29 download

DESCRIPTION

Конкурентно Програмиране. Семафори: използване за решаване на основни синхронизационни проблеми. Задача за обядващите философи. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Конкурентно Програмиране

Конкурентно програмиране 2005 1

Конкурентно Програмиране

Семафори: използване за решаване на основни синхронизационни проблеми

Page 2: Конкурентно Програмиране

Конкурентно програмиране 2005 2

Задача за обядващите философи

Постановка на задачата: Петима философи прекарват времето си като мислят или се хранят. Последното правят около кръгла маса, в средата на която е поставена купа със спагети. Пред всеки философ има чиния, а между всеки две чинии – една вилица. За да може да яде спагети, всеки философ се нуждае от две вилици, като има право да ползва тези, които са от двете страни на неговата чиния.

Тук трябва да се решат следните синхронизационни проблеми:

- всяка вилица да се използва най-много от един философ;

- да не се допуска deadlock, т.е. да се окаже, че всеки философ е взел една вилица и чака да се освободи втората, което никога няма да стане;

- да е гарантирано, че никой философ няма да умре от глад.

Илюстрация на проблема за възникването на deadlock:

Процесите са в deadlock ако чакат събитие, което никога няма да настъпи.

Най-чесно възникването на deadlock се свързва с управление на ресурсите.

Page 3: Конкурентно Програмиране

Конкурентно програмиране 2005 3

Необходими условия за възникване на deadlock:

- Монополен достъп до ресурсите;

- Процесът държи едни ресурси докато чака да получи други;

- Ресурсите не могат да бъдат отнемани насилствено от процес, който ги държи чакайки;

- Има затворен кръг от процеси, всеки от които държи ресурс, искан от следващия процес в кръга.

- Едновременно наличие на горните условия.

Техниките за предпазване от възникването на deadlock са основани на нарушаване на някое от тези условия.

Техниките за избягване на deadlock се състоят в мониториране на разпределението на ресурсите така, че да се открива потенциалната поява на deadlock и да се предотвратява.

Page 4: Конкурентно Програмиране

Конкурентно програмиране 2005 4

Решение на задачата за обядващите философи със семафори

Първо решение: общ ресурс е всяка една от вилиците, съответно нейната употреба се обявява за КУ и се защитава с отделен семафор.

Semaphore fork [5] = {1,1,1,1,1};

Process Philosopher_i

while (true) {

think();

P.fork[i];

P.fork[(i+1)%5];

eat();

V.fork[i];

V.fork[(i+1)%5];

}

End Philosopher_i;

При каква последователност от изпълнения на действията на процесите възниква deadlock?

Page 5: Конкурентно Програмиране

Конкурентно програмиране 2005 5

Възможни решения за предпазване от възникването на deadlock:

- да се получават едновременно двете вилици;

- да се разкъса кръга от процеси, всеки от които е заел единия ресурс и чака достъп до другия:

- един от процесите да размени реда, в който се опитва да вземе вилиците, например като всеки посяга първо към вилицата с по-малък номер;

- процесите с четни номера да вземат първо лявата си вилица, а тези с нечетни номера – първо дясната;

- да се ограничи броя на едновременно седящите около масата философи до 4. Това може да стане за сметка на добавяне на още един семафор-брояч, който управлява достъпа до масата:

Semaphore table = 4;

Process Philosopher_i

P.table;

. . . . . . .

V.table;

end Philosopher_i

Page 6: Конкурентно Програмиране

Конкурентно програмиране 2005 6

Задача Читатели/Писатели

Модел на работа с общи дани – конкурентно изпълнение на неограничен брой процеси: Читатели, които само четат данните и Писатели, които ги променят.

Изискванията са данните да не се ползват едновременно от:

- двама Писатели;

- Писател и Читатели.

Решенията имат за цел:

- да подсигурят горните изисквания;

- да не налагат недопустимо намаление на конкурентността.

Първо решение:Semaphore rw=1;

Process Reader Process Writer

P.rw; P.rw;

readData(); writeData();

V.rw; V.rw;

End Reader end Writer

Недопустимо ограничаване на конкурентния достъп до данните.

Page 7: Конкурентно Програмиране

Конкурентно програмиране 2005 7

Второ решение – отслабване на ограничението:

Semaphore rw=1, mutex=1;

int nR=0; // number of active Readers

Process Reader

. . . . . . . . .

P.mutex;

nR++;

if (nR==1) P.rw;

V.mutex;

readData();

P.mutex;

nR--;

if (nR==0) V.rw;

V.mutex;

. . . . . . . .

End Reader

Process Writer

. . . . . . . . .

P.rw;

writeData();

V.rw;

. . . . . .

End Writer

Позволено е на повече Читатели да имат конкурентен достъп до данните.

Въпроси:

- Как и къде блокират Читателите и Писателите?

- Какво става при напускане на Писател?

- Кой има приоритет?

Page 8: Конкурентно Програмиране

Конкурентно програмиране 2005 8

Читатели/Писатели – предаване на щафетата

Предаване на щафетата – метод, който:

- позволява да се решават различни синхронизационни проблеми;

- води до решения, които лесно се променят така, че да се смени стратегията на планиране.

Определяме предикат, характеризиращ “добрите” и “лошите” състояния на системата.

Нека nR - е броят на активните Читатели

nW - е броят на активните Писатели

“Лоши” състояния: (nR>0 && nW>0) || (nW>1)

“Добри” състояния: RW: (nR=0 || nW==0) && (nW<=1)

RW е глобален инвариант на системата

Reader:

< await (nW==0) nR++;>

read

< nR--; >

Writer:

< await (nR==0 && nW==0) nW++;>

write

< nW--; >

Page 9: Конкурентно Програмиране

Конкурентно програмиране 2005 9

В < > са означени атомарни действия на процесите.

await(B) S; има смисъл: условието В е гарантирано при изпълнението на S.

“Предаването на щафетата” използва SPB за осигуряване на ВИ, реализация на await(B) и контрол на реда, по който се събуждат блокираните процеси.

Въвежда се:

- един двоичен семафор за контрол на достъпа до атомарните действия;

- за всяко условие /гард/ В:

- един семафор с начална стойност 0;

- един брояч с начална стойност 0.

Семафорите общо формират един SPB.

int nR=0, nW=0;

Semaphore entry=1, // CS control

semR=0, // delay Readers

semW=0; // delay Writers

// SPB: 0<= entry+semR+semW<=1

int dR=0, // number of delayed Readers

dW=0; // number of delayed Writers

Page 10: Конкурентно Програмиране

Конкурентно програмиране 2005 10

Process Reader

while (true) {

// await (nW==0) => nR++

P.entry;

if (nW>0) {

dR++; V.entry; P.semR; }

nR++;

signal();

readData();

// nR—

P.entry;

nR--;

signal();

}

end Reader

Process Writer

while (true) {

// await (nR==0 && nW==0) => nW++

P.entry;

if (nR>0 || nW>0) {

dW++; V.entry; P.semW; }

nW++;

signal();

writeData();

// nW—

P.entry;

nW--;

signal();

}

end Writer

Page 11: Конкурентно Програмиране

Конкурентно програмиране 2005 11

Какво прави signal - решава на кого да предаде щафетата:

- на следващ Читател;

- на следващ Писател;

- да я остави.

signal() {

// awaken a Reader?

if (nW==0 && dR>0) {

dR--; V.semR; }

// awakan a Writer?

else if (nR==0 && nW==0 && dW>0) {

dW--; V.semW; }

// put baton down

else

V.entry;

}

Page 12: Конкурентно Програмиране

Конкурентно програмиране 2005 12

Читатели/Писатели – Условен критичен участък

resource Control: {int nR=0; boolean isWriting=false;}

Process Writer

with Control when (nR==0 & !isWritimg) do

isWriting=true;

writeData();

with Control when (true) do

isWriting=false;

End Writer;

Process Reader

with Control when (!isWritimg) do

nR++;

readData();

with Control when (true) do

nR--;

End Reader;

Page 13: Конкурентно Програмиране

Конкурентно програмиране 2005 13

Задачата за спящия бръснар

Постановка на задачата: В бръснарски салон работи един бръснар и има няколко стола за чакащи. Посетител, който влезе в салона и види, че в момента бръснарят подстригва някого сяда и чака, а ако няма свободни столове си тръгва. Ако няма други клиенти, посетителят може да завари бръснаря да дреме, тогава го събужда и сяда за подстригване.

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

Задачата е илюстрация на типа отношения клиент-сървер между конкурентните процеси. Взаимодействието на процесите – рандеву, носи името си от това, че два процеса трябва “да се срещнат” в дадена точка от своето изпълнение, за да могат да продължат коректно работата си с изпълнение на “общо действие”. Това става за сметка на забавяне на процеса, който първи е пристигнал на мястото на срещата.

Следва просто решение на задачата с използване на семафори за синхронизиране на процеса “бръснар” и процесите “посетители”.

Semaphore mutex=1; // за взаимно изключване

Semaphore customers=0, // бръснарят чака клиент

barber=0; // клиентите чакат бръснар

int numChairs= n, waiting=0; // брой чакащи клиенти

Page 14: Конкурентно Програмиране

Конкурентно програмиране 2005 14

Задачата за спящия бръснар – решение със семафори

Process Customer_i while (true) { P.mutex; // иска достъп до 'waiting' if (waiting<numChairs) { // ако има свободен стол - чака waiting++; // увеличава броя на чакащи клиенти V.customers; // събужда бръснаря, ако спи V.mutex; // освобождава достъпа до 'waiting' P.barber; // чака ако бръснарят не е свободен getHairCut(); // клиентът получава услугата } else V.mutex; // иначе напуска } end Customer;

Process SleepingBarber while (true) { P.customers; // задрямва ако няма клиенти P.mutex; // иска достъп до 'waiting' waiting--; // намалява броя на чакщите клиенти V.barber; // бръснарят е готов да подстригва V.mutex; // освобождава 'waiting' cutHair(); // сърверът обслужва } end SleepingBarber;

Page 15: Конкурентно Програмиране

Конкурентно програмиране 2005 15

Задача за разпределение на ресурси - Планировчик

Две основни операции:

- заемане на ресурс:

request(param)

await (resource available)

take units

- освобождаване на ресурс:

release(param)

return units

Пример - Shortest-Job-Next Resource Allocator за единичен ресурс

boolean free=true;

request (pid, time) {

await (free)

take resource

free=false }

release (pid) {

if (process delayed)

awaken one

else

free=true }

Page 16: Конкурентно Програмиране

Конкурентно програмиране 2005 16

boolean free=true;

Semaphore entry=1, b [n]={[n] 0};

PriorityQueue q=new PriorityQueue();

request (time, pid) {

P.entry;

if (!free) {

q.enqueue(time, pid);

V.entry;

P.b[pid];

}

free=false;

V.entry;

}

release (pid) {

P.entry;

if (!q.empty()) {

pid=q.dequeue();

V.b[pid];

}

else

free=true;

V.entry;

}