synchronizacja wątków w programowaniu współbieżnym

0

Witam! :-)

Jestem świeży w współbieżności i nie bardzo wiem jak ją zastosować w javie...
Piszę program szukający liczb doskonałych i nie wiem jak zsynchronizować ze sobą metody:
getElem - pobiera następny element z tablicy
check - sprawdza czy pobrana liczba jest liczbą doskonałą
sort - metoda sorująca tablicę...

jest ktoś w stanie coś podpowiedzieć, dopisać, nakierować?

oto kod, który już napisałem:

class Watek extends Thread{
    int[] m_Table;    
    int m_Elem;    
    int m_ElemIndexT;        
    //int ile_zostalo = Main.m_Table.length;
    
    public Watek(int[] table){
        m_Table = table;      
    }

    public synchronized boolean getElem(int indexElem){
        m_ElemIndexT = indexElem;
        if (indexElem < m_Table.length){
            m_Elem = m_Table[indexElem];
            return true;          
        }else{        
            return false;
        }
    }
    
    public synchronized void sort(){     
        int tmp;
        for (int i = m_ElemIndexT; i < m_Table.length - 1; i++) {
            if (m_Table[i] > m_Table[i + 1]) {
                tmp = m_Table[i];
                m_Table[i] = m_Table[i + 1];
                m_Table[i + 1] = tmp;
            }
        }                         
    }
    
    public synchronized void check(){
        int suma;
        int i=m_Elem;
        int b, j;
        int half;

        suma = 0; // zmienna pomocnicza suma.
        half = (i+1)/2;
        for(b=1; b<=half; b++)
        { // Sprawdzamy wszystkie liczby w pętli, od 1 do naszej obecnej "i"
            if(i%b==0){ // sprawdzamy czy jest podzielnikiem i
                suma+=b; // dodajemy ta liczbe do sumy
            }
        }        
        // Znaleziono liczbę doskonałą        
        if(suma==i){ // suma podzielników jest równa liczbie?            
            System.out.println("Liczba "+i+" jest liczba doskonala."); // Poinformuj, że liczba "i" jest liczbą doskonałą
            Main.m_NextIndex++;
            //ile_zostalo--;
        }
        // Liczba nie jest doskonała
        else{
            m_Table[Main.m_NextIndex] = m_Table[m_Table.length-1];     
            m_Table[m_Table.length-1]++;                       
            sort();           
        }     
      //suma=0; // zerujemy zmienną pomocniczą "suma" dla tego przebiegu funkcji.       
    }
    
    public void run(){
        try {
            sleep(10);                                           
            }
        catch (InterruptedException ex){            
        }
        while (getElem(Main.m_NextIndex)){               
            check();            
        }
    }
}
        

public class Main {
        
    static int m_NextIndex = 0;    
    static int[] m_Table;       
    
    public static void main(String[] args) {
    
        int maxTable = 5; //wyszukujemy 5 liczb doskonałych                       
        m_Table = new int[maxTable];             
        
        for (int i=0; i < m_Table.length; i++){
            m_Table[i] = i+1;
        }
       
        for (int i=0; i < 5;i++){ //uruchamiamy 5 wątków
            Watek w = new Watek(m_Table);
            w.start();
        }                                                        
   }
}

Proszę o pomoc [browar]
wielkie dzięki :-)
Pozdrawiam serdecznie :)

0

Niestety w tym kodzie NIC nie jest synchronizowane.

Metody typu synchronized znajdują się w klasie Watek i gdy zostaje wywołana któraś z tych metod, to następuje synchronizacja na poszczególnym wątku.(wątek sam na sobie się synchronizuje co nic nie daje).

public synchronized ....{
}

co jest równoważne z

public  ....{
 synchronized (this){ //this jest instancją klasy Watek

  }
}

zamień na

public  ....{
 synchronized (Watek.class){

  }
}

Kolejna sprawa, dlaczego chcesz wszystko synchronizować - jest to bez sensu. W danej chwili tylko jeden wątek będzie cokolwiek robił, bo reszta będzie na niego czekała. Jedynymi metodami, które muszą być synchronizowane, to metody do pobierania danych i wstawiania gotowego wyniku.

Jeszcze jedna rzecz-twoja metoda sort() nie sortuje poprawnie. Zapoznaj się z metodą Arrays.sort() (http://java.sun.com/javase/6/docs/api/java/util/Arrays.html)

0

dzięki za pomoc... sortowanie już działa prawidłowo - skorzystałem z Twojej rady :)

jednak co do tej synchronizacji to nadal wszystko odbywa się po staremu, czyli nic nie jest zsynchronizowane , mimo zastosowania rad... :( tzn. bywa tak, że różne wątki odwołują się do wcześniej sprawdzonych liczb... a o ile dobrze rozumiem to tak być nie powinno... zechciałby ktoś to wytłumaczyć jeszcze bardziej "łopatologicznie"...
Pozdrawiam

0

Wprawdzie niezbyt rozumiem ten algorytm, ale dostęp do zmiennej Main.m_NextIndex musi byś zsynchronizowany.

Pobierasz wartość tej zmiennej w run(), a robisz Main.m_NextIndex++ dopiero w check().
Musisz te dwie operacje-odczytanie wartości i zmiana licznika wykonać atomowo.

napisz coś takiego

private int getAndIncNextIndex(){
 synchronized(Watek.class){
   Main.m_NextIndex++;
   return Main.m_NextIndex - 1;
 }
}

Jednak lepiej wykorzystać standardową klasę AtomicInteger
http://java.sun.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html

0

oki, wielkie dzięki ;-)

rozwiązałem wszystko za pomocą strażnika tablicy, utworzyłem kolejną klasę i już wszystko myka jak należy :)

Pozdrawiam :)

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