2015-09-22 8 views
5

Ich habe eine Methode namens processOutbox. Ich möchte, dass es threadsicher ist. Ich möchte nicht, dass ein anderer Thread diese Methode aufruft, solange ein Thread dran ist. Ich habe es folgendermaßen umgesetzt. Habe ich es richtig gemacht? Gibt es Lücken in meiner Implementierung? Wenn es welche gibt, bitte beraten Sie, wie ich es lösen kann.Wie kann ich die Fadensicherheit in folgendem Zusammenhang sicherstellen?

this.start(); 
    outboxLock.lock(); 
    timer = new Timer(); 
    try{ 
    timer.scheduleAtFixedRate(new TimerTask() { 
      public void run() { 
       processOutbox(); 
      } 
     }, 0, period); 
    } finally{ 
     outboxLock.unlock(); 
    } 
+4

Sie haben nur die Planung gesperrt. Die Ausführung ist immer noch nicht threadsicher. – Fildor

+0

Wie mache ich es dann? Bitte um Rat. – mayooran

+0

Ich würde vorschlagen, es auf statische Variable auf Klassenebene zu synchronisieren. –

Antwort

5

Wenn Sie Ihre Methode processOutbox machen wollen, sollten Sie das Schlüsselwort synchronized:

public class YourClass{ 
    public synchronized void processOutbox(){ 
     //do all you want 
    } 
} 

Mehr Infos unter: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

Wenn in Ihrem Code Sie haben eine Instanz von Yourclass genannt Zum Beispiel myInstance, alle Aufrufe an processOutbox() sind threadsicher, da sie auf Instanzenebene gesperrt werden.

Zum Beispiel:

YourClass myInstance = new YourClass(); 
Thread thread1 = new Thread(){ 
    public void run(){ 
     myInstance.processOutbox(); 
    } 
    } 
Thread thread2 = new Thread(){ 
    public void run(){ 
     myInstance.processOutbox(); 
    } 
    } 
thread1.start(); 
thread2.start(); 

Hier thead2 warten wird, bis thread1 den Anruf beendet zu "processOutbox"

Aber zum Beispiel:

YourClass myInstance = new YourClass(); 
YourClass myInstance2= new YourClass(); 
Thread thread1 = new Thread(){ 
    @Override 
    public void run(){ 
     myInstance.processOutbox(); 
    } 
}; 
Thread thread2 = new Thread(){ 
    @Override 
    public void run(){ 
     myInstance2.processOutbox(); 
    } 
} 
thread1.start(); 
thread2.start(); 

thead2 wird NICHT warten, weil Sie rufen die Methode für verschiedene Instanzen auf.

Jemand fragte speziell nach der Verwendung von ReentrantLock - also füge ich diese Antwort zu diesem hier hinzu, weil dieser richtig ist.

public class YourClass { 
    private Lock outboxLock = new ReentrantLock(); 
    public void processOutbox() { 
     outboxLock.lock() 
     try { 
      // do stuff 
     } finally { 
      outboxLock.unlock() 
     } 
    } 
} 

Ich erwähne dies ausdrücklich, weil man auch Dinge tun kann, wo man andere Themen halten aus dem Schloss ohne sie verursacht durch die Verwendung TryLock anstatt zu blockieren.

public class YourClass { 
    private Lock outboxLock = new ReentrantLock(); 
    public void processOutbox() { 
     if(outboxLock.tryLock()) { 
      try { 
       // do stuff 
      } finally { 
       outboxLock.unlock() 
      } 
     } 
    } 
} 
+0

** Ich möchte nicht, dass ein anderer Thread diese Methode aufruft, solange ein Thread aktiv ist. ** –

+0

Java-API: "Wenn ein Thread eine synchronisierte Methode für ein Objekt ausführt, rufen alle anderen Threads synchronisierte Methoden für denselben Thread auf Objektblock (Ausführung aussetzen), bis der erste Thread mit dem Objekt fertig ist. " –

+0

Wie erreiche ich dasselbe mit Reentrantlock? bitte beraten goku :) – mayooran

Verwandte Themen