Czy ten (krótki) kod spełnia pożądany warunek

0

Program współbieżny składa się z dwóch wątków X i Y. W celu realizacji wzajemnego wykluczania - w przypadku
tych dwóch wątków - student A1 zaproponował następujący protokół.

Idea podstawowa: wątek X może zmieniać stan swojej zmiennej stanX i sprawdzać zmienną stanY „należącą” do
wątku Y. Analogicznie działa wątek Y.

Gdy wątek X chce wejśd do sekcji krytycznej, to ustawia stanX na 1, a następnie sprawdza stan zmiennej partnera,
czyli stanY:

  • jeśli stanY == 1, to proces X natychmiast ustawia stanX na 0 i po losowej chwili ponawia próbę; czyli
    ustawia stanX na 1, testuje zmienną stanY etc.
  • jeśli stanY == 0, to proces X wchodzi do sekcji krytycznej i przez pewien czas wykonuje działania na
    zasobie dzielonym.

Z chwilą opuszczenia sekcji krytycznej proces X ustawia zmienną stanX na 0.

Proces Y realizuje analogiczny protokół wejścia do sekcji krytycznej, tzn. ustawia stanY na 1, a następnie sprawdza
stan zmiennej partnera, czyli stanX etc.

a)
Napisz demonstracyjny program współbieżny wyłącznie w oparciu o ten algorytmem realizacji wzajemnego
wykluczania ( np. dwa procesy n-razy inkrementują zmienną dzieloną typu int).

public class Roboczy extends Thread{
    
    private String name;
    private int stanX, stanY;
    private static Integer zmDzielona=0;
    
    public Roboczy(String name){
        this.name=name;
        
    }
    
    @Override
    public void run(){
        
        if(name.equals("X")){
            stanX=1;
            
            if(stanY==1){
                    try {
                        stanX = 0;
                        sleep((int) (Math.random() * 5000));
                    } catch (InterruptedException ex) {}
            }
            else if(stanY==0){ //warunek wejscia do sekcji krytycznej
                synchronized(zmDzielona){
                    for(int i=0; i<10; i++){
                        zmDzielona++;
                        System.out.println("Watek " +name+ ":" +zmDzielona);
                    }
                }
                stanX=0;
            } 
        } 
    }

}
 

Nie do końca rozumiem warunek gdy stanY jest równy 1, czy kod pasuje do treści zadania?

PS. Algorytm ten ma wady.

0

Jest prawie ok. Jednak:
-nie możesz się synchronizować na zmiennej zmDzielona, gdyż obiekt pod tą zmienną się zmienia (poprzez zmDzielona++). Synchronizuj się np. na obiekcie klasy wątku - synchronized(Roboczy.class) { ...
-zmienne stanX i stanY muszą być statyczne (muszą być współdzielone przez obydwa wątki)
-zmienne stanX i stanY muszę być oznaczone jako voliatile, gdyż dostęp do nich jest poza sekcją krytyczną
-musisz napisać część dla wątku Y

0

Klasa główna:

 
public class Glowna {
    
    public static void main(String[] args){
        Roboczy thX = new Roboczy("X");
        Roboczy thY = new Roboczy("Y");
        thX.start();
        thY.start();
    }

}

Klasa robocza:

public class Roboczy extends Thread{
    
    private String name;
    private volatile int stanX, stanY; 
    private int n=10;
    private static Integer zmDzielona=0;
    
    public Roboczy(String name){
        this.name=name;
        
    }
    
    @Override
    public synchronized void run(){
        
        if(name.equals("X")){
            stanX=1;
            
            if(stanY==1){
                    try {
                        stanX = 0;
                        sleep((int) (Math.random() * 100));
                    } catch (InterruptedException ex) {}
            }
            else if(stanY==0){ //warunek wejscia do sekcji krytycznej
                synchronized(Roboczy.class){
                    for(int i=0; i<n; i++){
                        zmDzielona++;
                        System.out.println("Watek " +name+ ":" +zmDzielona);
                    }
                }
                stanX=0;
            } 
        }
        
        else if(name.equals("Y")){
            stanY=1;
            
            if(stanX==1){
                    try {
                        stanY = 0;
                        sleep((int) (Math.random() * 100));
                    } catch (InterruptedException ex) {}
            }
            else if(stanX==0){ //warunek wejscia do sekcji krytycznej
                synchronized(Roboczy.class){
                    for(int i=0; i<n; i++){
                        zmDzielona++;
                        System.out.println("Watek " +name+ ":" +zmDzielona);
                    }
                }
                stanY=0;
            } 
        }
    }
}
 

Natomiast, jeśli zamiast:

private volatile int stanX, stanY;

Dam:

private volatile static int stanX, stanY;

To zwraca mi tylko wartości dla X'a. Czyli:
Watek X:1
Watek X:2
...
Watek X:10

0

Mój błąd, zamiast

public synchronized void run(){

ma być:

public void run(){

Lecz nie zmienia to postaci rzeczy jeśli chodzi o static dla zmiennych stanX i stanY.

I jakie wady ma ten algorytm jeśli stosuję synchronized? Czy ma?:)
Bo dalej w poleceniu zadania mam, że student B znalazł oczywiste wady i mam je uzasadnić. Jeśli nie będzie synchronized to wiadomo.

1 użytkowników online, w tym zalogowanych: 0, gości: 1