publicclassNameOutputextendsThread{privatestaticint NUMBER_OF_THREAD =11;privatestaticint number =0;privatestaticObject lock =newObject();privatestaticint next =1;privateint myNumber;publicNameOutput(){}publicvoidrun(){while(true){synchronized(lock){
number++;if(number == next){System.out.println(getName()+": "+": "+ next +": "+ number);try{Thread.sleep(500);}catch(InterruptedException e){
e.printStackTrace();}
next =(next +1)% NUMBER_OF_THREAD;
lock.notifyAll();}else{try{
number=0;
lock.wait();}catch(InterruptedException e){
e.printStackTrace();}}}}}publicstaticvoidmain(String[] args){newNameOutput().start();newNameOutput().start();newNameOutput().start();}
ich möchte ein kleines Programm schreiben, so dass jeder Thread seinen Namen jeweils zehnmal hintereinander ausgibt, ohne dass ihm einer der anderen Threads dazwischenfunkt.
Irgendwo gibt es bei mir Deadlock, kann jemand mich bitte unterstützen?
synchronized funktioniert anders als du denkst in diesem Kontext. Effektiv ist das betreten des synchronized-Blocks mit einem Thread eine Sperre fuer alle anderen. Also alle anderen Threads bleiben beim synchronized stehen und warten darauf dass die Sperre vom ersten Thread freigegeben wird.
Dieser erste Thread landet aber irgendwann beim lock.wait(), was bedeutet er wartet darauf dass ein anderer Thread das Signal gibt das es weiter geht. Aber kein anderer Thread kann dieses Signal geben weil alle beim synchronized stehen. Ohne jetzt grosz darueber nachgedacht zu haben, wahrscheinlich brauchst du das erste synchronized nicht.
Jeder Thread ist immer berechtig auf die gemeinsamen Variablen zuzugreifen.
Mit der Variablen “number“ willst du das ja steuern . Also solltest du den Zugriff auf diese Variable Steuern.
Das ist nicht korrekt. Ein object.wait() löst den Lock desselben Objektes, sodass andere Threads den synchronized Bereich betreten können.
Tatsächlich kann man object.wait() nur aufrufen, wenn man vorher den Lock auf das Objekt hat.
Das ist nicht korrekt. Ein object.wait() löst den Lock desselben Objektes, sodass andere Threads den synchronized Bereich betreten können.
Tatsächlich kann man object.wait() nur aufrufen, wenn man vorher den Lock auf das Objekt hat.
Ohhh...das hatte ich dann uebersehen. Ich kenne es nur als Konstrukt wie du meinst, und dachte immer das waere eine Sondersache. Dann nehme ich das zurueck...
ich möchte ein kleines Programm schreiben, so dass jeder Thread seinen Namen jeweils zehnmal hintereinander ausgibt, ohne dass ihm einer der anderen Threads dazwischenfunkt.
publicclassWorkerimplementsRunnable{privateObject lock;publicWorker(Object lock){this.lock = lock;}publicvoidrun(){synchronized(lock){zeige10MalMeinenNamen();}}privatevoidzeige10MalMeinenNamen(){for(int i =0; i <10; i++){System.out.println(Thread.currentThread().getName());}}}
publicclassWorkerimplementsRunnable{privateObject lock;publicWorker(Object lock){this.lock = lock;}publicvoidrun(){synchronized(lock){zeige10MalMeinenNamen();}}privatevoidzeige10MalMeinenNamen(){for(int i =0; i <10; i++){System.out.println(Thread.currentThread().getName());}}}
Dein Code funktioniert korrekt, ich hätte eine Frage zu "lock". Warum hast Du es in der Methode main initialisiert und dann an Constructor übergeben? Also warum funktioniert nicht, wenn man direkt im Constructor z.B " public Worker() {
lock = new Obect()
}
initialisiert?
Die lock-Variable existiert pro Instanz. Es muss aber sichergestellt sein, dass die Synchronisation in allen Worker-Instanzen über das selbe(!) Objekt stattfindet. Daher ist es korrekt, wenn ein lock-Objekt erzeugt wird, das allen Worker-Instanzen zur Synchronisation zur Verfügung gestellt wird. Das ist letztlich nur eine Alternative zur statischen lock-Variable, wie Du sie verwendet hast.