/ / Java: zapobieganie zakleszczeniu w tym przykładzie - java, wielowątkowość, współbieżność, synchronizacja

Java: zapobieganie zakleszczeniom w tym przykładzie - Java, wielowątkowość, współbieżność, synchronizacja

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 № 1

Kiedy 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.