alle (oder eine Gruppe von) Threads warten, bis alle an einer Stelle angekommen sind.
Datentyp barrier_t
int barrier_init(barrier_t *bp, int max);
int barrier_wait(barrier_t *bp );
int barrier_destroy(barrier_t *bp );
Sourcen:
| barrier1.h | Header für 1. Version |
| barrier1.c | Implementierung |
Barrier-Typ enthält:
barrier_wait:
lock
inkrementiere Anzahl cnt der angekommenen Threads
Wenn ich der letzte bin:
setze cnt = 0 (für die nächste Barrier)
wecke alle anderen
sonst
warte bis zum Wecken
(cnt muß dann 0 sein!)
unlock
Race-Condition bei einer zweiten Barrier:
maxcnt = 2,
Thread 0 Thread 1 cnt
barrier1 barrier1 0
lock
cnt++ 1
wait/unlock
lock
cnt++ 2
max -> cnt = 0 0
broadcast
unlock
barrier2
lock
wird wach,
lock besetzt
cnt++ 1
wait/unlock
bekommt lock
while (cnt>0)
wait/unlock
DEADLOCK !
Problem: cnt ist gleichzeitig Zähler der Wartenden und in cnt==0 die Durchschaltbedingung für die Barrier. Bei einer zweiten Barrier geraten beide Funktionen in Konflikt.
Lösung: zusätzliche Variable barrier->phase als Durchschaltbedingung. Dadurch ist der neue Wert cnt=1 für die anderen irrelevant
Sourcen:
| barrier.h | Header für korrigierte Version |
| barrier.c | Implementierung |
barrier_wait:
lock
merke dir den Wert von phase
inkrementiere Anzahl cnt der angekommenen Threads
Wenn ich der letzte bin:
setze cnt = 0 (für die nächste Barrier)
toggle phase
wecke alle anderen
sonst
warte bis zum Wecken
(phase muß sich geändert haben!)
unlock
zum Vergleich:
Thread 0 Thread 1 cnt phase
barrier1 barrier1 0 0
lock
my_phase=0
cnt++ 1
wait/unlock
lock
my_phase=0
cnt++ 2
max -> cnt = 0 0
phase = 1-phase 1
broadcast
phase != my_phase
-> unlock
barrier2
lock
wird wach,
lock besetzt
my_phase=1
cnt++ 1
wait/unlock
bekommt lock
phase != my_phase
-> unlock