Próbuję ćwiczyć moje rozumieniewspółbieżność w Javie, oto problem: Może istnieć wiele wątków z uruchomioną metodą A i tylko jeden wątek z uruchomioną metodą B (powiedzmy, gdy A () uruchomił się 10 razy. Więc po raz dziesiąty wątek uruchomi metodę B. Gdy to się stanie, musi zablokować wątki z uruchamiając A i zezwalając wątkom, które już działają, na A, przed uruchomieniem reszty B. Również wątki w A nie powinny czekać na siebie.
edytuj: Wszystkie wątki są uruchamiane po raz pierwszy, istnieje zewnętrzna metoda, która sprawdza, kiedy uruchomić B.
Moja dotychczasowa próba wygląda mniej więcej tak:
volatile Boolean lock = false; //false = threads in method A allowed to run, thread in method B otherwise
volatile Integer countOfA = 0;
void A(){
boolean continue = false;
synchronized(lock){
if(lock == true){ //there is a thread in B, block threads in A
lock.wait();
increaseCountOfA();
//do work
decreaseCountOfA();
if(countOfA == 0){ //this was the last thread that ran with lock
lock = true;
lock.notify(); //only the thread in B should be waiting on this
}
}else{
continue = true;
}
}
if(continue){
increaseCountOfA();
//do work;
decreaseCountOfA();
}
}
void B(){
synchronized(lock){
if(lock == false){
lock.wait();
if(countOfA > 0){
countOfA.wait();
}
//do work;
lock = false;
lock.notifyAll();
}
}
}
void increaseCountOfA(){
synchronized(countOfA){
countOfA++;
}
}
void decreaseCountOfA(){
synchronized(countOfA){
countOfA--;
}
}
Gdy biegnie, zawiesza się. Podejrzewam impas, nie wiem też, ile poziomów synchronizacji jest potrzebnych do tego problemu. Czy można to zrobić za pomocą jednego poziomu?
Odpowiedzi:
0 dla odpowiedzi № 1Kiedy to zrobisz synchronized(lock)
synchronizujesz obiekt, do którego odnosi się lock
, nie na zmiennej. Prawdopodobnie chcesz niezależnego obiektu blokady, którego wartość nie zmieniasz. Alternatywnie możesz rozważyć użycie klasy współbieżności wyższego poziomu, takiej jak Semaphore
.
W tym przypadku masz jeden wątek czekający Boolean.TRUE
, a inny wpis na powiadomienie Boolean.FALSE
.