2009-07-16 6 views
-2

Ich habe Probleme mit synchronisiertem die Art und Weise nicht verhalten erwarte ich, habe ich versucht, auch flüchtige Schlüsselwort:Java Synchronized und Themen

Shared Object:

public class ThreadValue { 

    private String caller; 
    private String value; 

    public ThreadValue(String caller, String value) { 
     this.value = value; 
     this.caller = caller; 
    } 

    public synchronized String getValue() { 
     return this.caller + "  " + this.value; 
    } 
    public synchronized void setValue(String caller, String value) { 
     this.caller = caller; 
     this.value = value; 
    } 
} 

Gewinde 1:

class CongoThread implements Runnable { 
    private ThreadValue v; 
    public CongoThread(ThreadValue v) { 
     this.v = v; 
    } 
    public void run() { 
     for (int i = 0; i < 10; i++) { 
      v.setValue("congo", "cool"); 
      v.getValue(); 
     } 
    } 
} 

Thread 2:

class CongoThread implements Runnable { 
    private ThreadValue v; 
    public CongoThread(ThreadValue v) { 
    this.v = v; 

    } 
    public void run() { 
     for (int i = 0; i < 10; i++) { 
      v.setValue("congo", "lame"); 
      v.getValue(); 
     } 
    } 
} 

Berufung Klasse:

class TwoThreadsTest { 
    public static void main (String args[]) { 

     ThreadValue v = new ThreadValue("", ""); 
     Thread congo = new Thread(new CongoThread(v)); 
     Thread libya = new Thread(new LibyaThread(v)); 

     libya.start(); 
     congo.start(); 
    } 
} 

Gelegentlich bekomme ich "In Libya Thread congo cool" , die nie passieren sollte. Ich erwarte nur:
"In Libya Thread libya awesome"
"In Congo Thread congo cool"

Ich erwarte nicht, sie zu mischen.

+1

Wie können Sie "In Libyen Thread libya awesome" erwarten? Ihr Programm enthält nicht das Wort "super" –

Antwort

1

Was passiert ist, die folgenden:

  1. Thread 1 setzt den Wert
  2. Thread 2 setzt den Wert
  3. Thread 1 den Wert von Thread 2.

gesetzt, um dies liest man 1 Sperrobjekt, muss das zu beheben, die die get bewacht/set functions rufen beide Threads auf. Der beste Weg, dies zu tun, besteht darin, eine zusätzliche synchronisierte Methode zu erstellen, die sowohl das Set als auch das Get ausführt. Manchmal ist das jedoch nicht wünschenswert. In diesem Fall geben Sie beiden Threads ein Sperrobjekt. Welches ist nur ein einfaches Objekt. Was sie dann in einem synchronisierten Block verwenden.

Implementierung von jedem Thread möchte wie folgt, beachten Sie, dass sie genau das gleiche Objekt haben müssen!

Object lockObject = new Object(); 
Thread t1 = new CongroThread(v, lockObject); 
Thread t2 = new LibyaThread(v, lockObject); 

... 

class CongoThread implements Runnable { 
    private ThreadValue v; 
    private Object lockObject; 

    public CongoThread(ThreadValue v, Object lockObject) { 
    this.v = v; 
    this.lockObject = lockObject, 
    } 
    public void run() { 
     for (int i = 0; i < 10; i++) { 
      synchronized(lockObject) 
      { 
       v.setValue("congo", "lame"); 
       v.getValue(); 
      } 
     } 
    } 
} 
0

Haben Sie die System.out.print-Aufrufe synchronisiert? Ohne Synchronisierung sind sie threadsicher, aber möglicherweise nicht in der richtigen Reihenfolge.

synchronzied(System.out) { 
    System.out.print(....); 
    System.out.flush(); 
} 
1

Sie synchronisieren nur Zugriff auf getValue und setValue separat nicht die Zweizeiler

v.setValue("congo", ..); 
v.getValue(); 

Dann natürlich die beiden Fäden verflechten kann zwischen jemandes setValue und getValue