Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Hi, mal ne Frage zum Thema Synchronisation, iwie blicke ich da noch nicht ganz durch.
Also wann sollte man Objekte mit synchronized schützen ? wenn gemeinsam gelesen wird ? Wenn ausschliesslich ein Thread schreibt aber 4 z.b. leben ? Oder erst wenn mehrere Threads gleichzeitig schreiben wollen ?
Lesen können beliebig viele Thread, das schadet nicht - sobald aber auch nur ein Thread den Zustand des Objektes verändern kann, muss sichergestellt werden, dass a) für die Dauer der Schreiboperation kein anderer Thread den Zustand entweder verändert oder liest und b) während einer Leseoperation kein anderer Thread den Zustand ändert. Insofern würde ich sagen. Antwort 2: ein Thread scheibt, alle anderen lesen - bereits in diesem Szenario müsste man sich mit Sychronisierung beschäftigen.
Ok, noch eine andere Sache, ich habe eine Klasse die sobald sie als Thread gestartet wird, (Sie implementiert Runnable)
eine Variable auf einen bestimmte nWert setzt in der Run methode. Diese Schreiboperation synchronisiere ich. Es gibt auch die Methode getValue, damit kann ich mit einem anderen Thread den Wert dieser Variable abfragen. Nicht synchronisiert.
Code:
Counter c = new Counter(0);
Thread t = new Thread(c);
t.start();
System.out.println(c.getValue());
So, bei c.getValue kommt 0, obwohl in der run() methode ja der interne counter um eins erhöht wird. So, mir ist klar, dass es eine gewisse Zeit dauert, den Thread zu starten. Nun meine Frage, wie kann man es realisieren, dass .start() erst wieder zurückspringt, wenn die run methode auch wirklich gestartet wird. Muss dafür wirklich einen Thread.sleep() Aufruf machen ? Das fände ich nicht sehr schön, davon abgesehen, kann man ja garnicht mit gewissheit sagen, wie lang ein pc bzw ein OS für sowas braucht. Also wie regelt man im Normalfall sowas ?
Naja :? wenn du getValue aufrufst, und der Wert ist 0, dann wird 0 zurückgegeben. Woher soll denn der, der sich die Information holen will, wissen, welchen Wert der Zähler gerade hat? (Macht ja auch keinen Sinn). Wenn du in einem Thread irgendwas machen willst, und in einem anderen nicht "irgendeinen (beliebigen) aktuellen Zustand" abholen willst, sondern tatsächlich das Ergebnis (einer Berechnung), dann klingt das eher nach Producer/Consumer, und könnte mit einer http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html gemacht werden. Aber beschreib' ggf. nochmal genauer, was du machen willst ... z.B. warum du da unbedingt genau die 1 haben willst, und nicht die 0, die 2 oder die 412331.
Du willst also den Thread, der den anderen Thread startet, warten lassen, bis der gestartete Thread an einer bestimmten Stelle in der run-Methode ist?
Dann wäre vielleicht auch eine CyclicBarrier das richtige. Da machst du eine neue CyclicBarrier(2) und sowohl direkt nach dem start() als auch an der entsprechenden Stelle im run myCyclicBarrier.await().
Ok, also das war nur ein Beispiel, mein PRoblem ist zur Zeit ein ganz anderes.
Ich schreibe eine Server Klasse mit java.nio.channels. So, und in der run()- methode, werden ein paar Variablen auf true gesetzt und dann in die while Schleife eingetreten. So wenn also mit .start() diesen Thread starte und danach direkt abfrage isRunning(), so gibt diese Methode false zurück, weil diese Variable erst in der run()- Methode als drittes gesetzt wird. Sprich das sieht dann iwie so aus:
Code:
Server s = new Server(1234);
Thread t = new Thread(s);
t.start();
s.isRunning() //Hier wird false zurück gegeben.
//////// Nun die run()-Methode
public void run()
{
synchronized(running)
{
running = Boolean.TRUE;
}
//...... noch weitere sachen ...
}
public boolean isRunning()
{
return running.BooleanValue();
}
So, das Problem ist gelöst, wenn ich nach der .start() Methode nen sleep(500) oder so mache. Aber das finde ich unschön. Ich dachte schon an wait(), notifyAll(), aber das wäre auch nicht perfekt:
Code:
Server s = new Server(1234);
Thread t = new Thread(s);
t.start();
synchronized(s)
{
s.wait();
}
s.isRunning() //Hier wird false zurück gegeben.
//////// Nun die run()-Methode
public void run()
{
synchronized(running)
{
running = Boolean.TRUE;
}
//...... noch weitere sachen ...
synchronized(this)
{
this.notifyAll();
}
}
public boolean isRunning()
{
return running.BooleanValue();
}
So, wenn aber mal aus irgendeinem Grund, der Thread eher gestartet wird, und aus irgendeinem Grund notifyAll vor dem wait() aufgerufen wird, gibt es ein Dauer warten bei wait(). Man könnte natürlich auch wait(1000), aber angenommen, der Server bräuchte aus ieinem Grund, (warum auch immer ,verbuggte VM oder iein dummer Zufall)
länger als 1000 ms, dann würde wait zwar nach 1 sekunde zurückspringen, doch running wäre dann immer noch gleich FALSE.
Verren ich mich vlt grade in was ? Also iwie bin ich da grad etwas verzweifelt, weil grade das gefühl habe, dass das was ich vor hab mit Java garnicht möglich ist..... Naja ich wäre froh wenn mir da einer helfen könnte das zu verstehen
Was ich oben geschrieben hab sollte da genau helfen. Kleines Beispiel:
Code:
import java.util.concurrent.CyclicBarrier;
public class ThreadExample {
public static void main(String[] args) {
CyclicBarrier initSynchronizer = new CyclicBarrier (2);
Server server = new Server(initSynchronizer);
new Thread(server).start();
try{
initSynchronizer.await();
}catch(Exception e){
e.printStackTrace();
}
System.out.println(server.isRunning());
System.exit(0);
}
}
class Server implements Runnable
{
private CyclicBarrier initSynchronizer;
private boolean running = false;
private int importantVariable = 0;
public Server (CyclicBarrier initSynchronizer){
this.initSynchronizer = initSynchronizer;
}
public void run()
{
init();
while(true){
// do some stuff
}
}
public boolean isRunning()
{
return running;
}
private void init()
{
for (int i = 0; i < 10000; i++){ // we need some time here
importantVariable = i * i;
}
running = true;
try{
initSynchronizer.await();
}catch(Exception e){
e.printStackTrace();
}
}
}