Threads wait() und notify()

KN4CK3R

Mitglied
Hallo,

ich habe mehrere Threads von denen jeder für seinen Nachfolger die Vorarbeit erledigt, woraufhin dieser mit seiner Arbeit weitermachen kann.
Jeder Thread besitzt eine Variable position auf die sein Nachfolger zugreifen kann. Jeder Thread bearbeitet ein Array und setzt position auf die Stelle, die er gerade bearbeitet. Der nachfolgende Thread muss mit seiner Arbeit solange warten bis parent.getPosition() - this.position > 2 ist.
Dazu hatte ich bisher folgenden Code:

Java:
while (parent.getPosition() - position < 2) {
    Thread.sleep(1);
}

Nun wollte ich das ganze aber nicht mit dem (meiner Meinung nach) unschönen Thread.sleep lösen, sondern mit einem Lock-Object, das ich per wait und notify synchronisieren wollte. Jeder Thread hat nun noch ein Object lock;, auf das der Nachfolger Zugriff hat. Nun hab ich aber das Problem, dass ich nicht weiß, wie ich das ganze nun benutzen soll, da mir bisher jeder Versuch eine IllegalMonitorStateException eingebracht hat.

Java:
void run() {
	Object parentLock = parent.getLockObject(); // ist das Object lock des Vorgängers (siehe Zeile 4)
	for (int i = 0; i < arrayWidth; ++i) {
		synchronized (lock) {
			while (parent.getPosition() - position < 2) {
				synchronized (parentLock) {
					wait();
				}
			}
			
			//do work
			
			notify();
		}
	}
}

greetz KN4CK3R
 
Kleiner allgemeiner Tipp: Vergiss wait() und notify() am besten völlig, und wenn möglich synchronized noch dazu. Schau dir stattdessen das Concurrency-Framework an. Das ist sehr viel schöner, einfacher und sicherer als diese Low-Level-Synchronisation. Hier könnte man vielleicht mit Locks und Conditions arbeiten.
 
hab mir das mal angeschaut und in meinem Fall wäre das wohl das richtige. Damit hätte ich doch aber immernoch das Problem, dass alles in einem lock.(un)lock(); gefangen wäre (vgl. meinem synchronized Block im Code oben) oder nicht?

greetz KN4CK3R
 
Was spricht gegen wait/notify? Ist doch einfach eigendlich sehr einfach.

Java:
import java.awt.EventQueue;
import java.util.concurrent.TimeUnit;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class Lock
{
	private static final Object LOCK = new Object();
	
	public static void main(String[] args)
	{
		EventQueue.invokeLater(new Runnable() {
			public void run()
			{
				JFrame frame = new JFrame();
				frame.add(new JLabel("Frame zum Beenden, Ausgabe -> Konsole"));
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.pack();
				frame.setLocationRelativeTo(null);
				frame.setVisible(true);
			}
		});
		
		new Thread() {
			public void run()
			{
				System.out.println("Thread A startet");
				
				do
				{
					System.out.println("Thread A wartet 4 Sekunden.");
					doSleeping(TimeUnit.SECONDS, 4L);
					
					System.out.println("Thread A weckt B auf.");
					doNotify();
				}
				while(true);
			}
		}.start();
		
		new Thread() {
			public void run()
			{
				System.out.println("Thread B startet");
				
				do
				{
					System.out.println("Thread B wartet auf A");
					doWaiting();
					System.out.println("Thread B wurde aufgeweckt und fährt nun fort.");
				}
				while(true);
			}
		}.start();
	}

	private static void doWaiting()
	{
		synchronized (LOCK)
		{
			try
			{
				LOCK.wait();
			}
			catch (InterruptedException e) {}
		}
	}
	private static void doNotify()
	{
		synchronized (LOCK)
		{
			LOCK.notifyAll();
		}
	}
	private static void doSleeping(TimeUnit timeUnit, long timeFactor)
	{
		try
		{
			timeUnit.sleep(timeFactor);
		}
		catch (InterruptedException e) {}
	}
}
 
KN4CK3R hat gesagt.:
das notify steckt schon in einem synchronized (siehe Zeile 4)
Du müsstest die Methoden aber auf den synchronisierten Objekten aufrufen:
Java:
Object lock = getLock();

synchronized (lock)
{
    lock.wait();
}
Momentan rufst du aber die Methoden auf dem 'umfassenden' Objekt auf.
 
@Volvagia: sieht sehr brauchbar aus, werde ich auf jeden Fall mal testen.
@Suinos: ich dachte innerhalb einem synchronized(obj) ist this = obj?

greetz KN4CK3R
 
ich dachte innerhalb einem synchronized(obj) ist this = obj?
Nein, das ist nicht der Fall.
synchronized bei der Deklaration einer (Instanz-)Methode hat zwar den gleichen Effekt wie ein synchronized( this)-Block um den gesamten Methodenkörper; das bedeutet aber nicht, dass durch einen synchronized-Block die Bedeutung von this geändert würde.
 

Neue Themen


Zurück
Oben