2016-06-02 6 views
2

CodebeispielWie wird der Feldwert zwischen den Laufflächen gewaltsam synchronisiert?

public class MyClass{ 
     private MyObject myObject;   
     private Object lockObject = new Object();   
     MyObjectFactory factory; 

     public MyClass(MyObjectFactory factory){ 
      this.factory = factory; 
     } 

     public MyObject GetObject() 
     { 
      if (myObject == null){ 
       lock(lockObject){ 
        myObject = factory.Create(); 
        //need forcibly sync myObject value beetween all threads here 
       } 
      } 
      return myObject; 
     } 
    } 

Instanz von MyClass gemeinsamen beetwen mehrere Threads. Ich weiß, dass ich volatile myObject verwenden kann und es Feldwert beim Schreiben synchronisieren wird, aber ich werde auch langsam lesen. Ist es möglich, myObject Wert nur einmal in Sperrabschnitt ohne flüchtige zu synchronisieren?

Antwort

2

Sie müssen Ihren Code leicht ändern, so dass es den Doppel Karomuster implementiert:

public MyObject GetObject() 
{ 
    if (myObject == null) 
    { 
     lock(lockObject) 
     { 
      if (myObject == null) 
      { 
       myObject = factory.Create(); 
      } 
     } 
    } 
    return myObject; 
} 

Wenn Ihr Code wird immer nur läuft auf x86/x64-Prozessoren, dann müssen Sie nicht das volatile Stichwort als Das CPU-Speichermodell ist stark genug, um sicherzustellen, dass andere Threads die Änderung in myObject entweder in der if-Anweisung oder definitiv in der zweiten if-Anweisung sehen, sobald die Sperre erfasst wurde.

Alternativ können Sie die LazyInitializer Klasse verwenden diese von Ihnen zu verstecken:

private MyObject myObject;   
    private Object lockObject;   
    private MyObjectFactory factory; 
    private bool initialized; 

    public MyObject GetObject() 
    { 
     return LazyInitializer.EnsureInitialized(ref myObject, ref initialized, ref lockObject, factory.Create) 
    } 

Hier finden Sie nehmen nur den Hit eines flüchtigen Lesen auf der boolean, wenn das Objekt bereits erstellt wurde. Beachten Sie, dass die Methode das Sperrobjekt für Sie zuweist, wenn Sie noch kein Sperrobjekt erstellt haben.

+0

Es ist interessant, Tatsache über x86/x64-Prozessoren. Ich denke, es wird eine Lösung für mich sein, weil unser Server einen x86-Prozessor verwendet. Aber ich habe theoretisches Interesse - ob es möglich ist, die Situation im Allgemeinen ohne Annahmen über die Prozessorarchitektur zu lösen? – Frank59

+1

Mit neuen Informationen ist es eine komplette Lösung für mich. Vielen Dank! – Frank59

0

In diesem Fall müssen Delegaten verwendet werden. Der Thread verwendet den Delegaten, um auf eine Methode im Hauptthread zuzugreifen, um Daten an ihn zu übergeben und die Aktion sofort zuzulassen, vorausgesetzt, dass Sie bei der Erstellung des Verknüpfungsthreads keine Verknüpfung verwendet haben.

Verwandte Themen