Lassen Sie mich dieses kleine und einfache Beispiel verwenden:
class Sample {
private String msg = null;
public void newmsg(String x){
msg = x;
}
public String getmsg(){
String temp = msg;
msg = null;
return temp;
}
}
Nehmen wir an, die Funktion newmsg()
wird von anderen Threads aufgerufen, auf die ich keinen Zugriff habe.
Ich möchte die Synchonisierungsmethode verwenden, um sicherzustellen, dass die Zeichenfolge msg
nur von einer Funktion pro Zeit verwendet wird. Mit anderen Worten, die Funktion newmsg()
kann nicht gleichzeitig mit ausgeführt werden getmsg()
.
java
synchronization
Winter
quelle
quelle
Antworten:
Das ist ziemlich einfach:
class Sample { private String message = null; private final Object lock = new Object(); public void newMessage(String x) { synchronized (lock) { message = x; } } public String getMessage() { synchronized (lock) { String temp = message; message = null; return temp; } } }
Beachten Sie, dass ich nicht entweder die Methoden machen sich synchronisiert oder synchronisieren auf
this
. Ich bin der festen Überzeugung, dass es eine gute Idee ist, Sperren nur für Objekte zu erwerben, auf die nur Ihr Code Zugriff hat, es sei denn, Sie legen die Sperre absichtlich offen. Es macht es viel einfacher, sich zu vergewissern, dass nichts anderes Sperren in einer anderen Reihenfolge als Ihr Code usw. erwerben wird.quelle
Für diese Funktionalität ist es besser, überhaupt kein Schloss zu verwenden. Versuchen Sie es mit einer AtomicReference.
public class Sample { private final AtomicReference<String> msg = new AtomicReference<String>(); public void setMsg(String x) { msg.set(x); } public String getMsg() { return msg.getAndSet(null); } }
Keine Sperren erforderlich und der Code ist meiner Meinung nach einfacher. In jedem Fall wird ein Standardkonstrukt verwendet, das das tut, was Sie wollen.
quelle
java.util.concurrent.atomic
AtomicBoolean
AtomicInteger
Ab Java 1.5 ist es immer eine gute Idee, das Paket java.util.concurrent in Betracht zu ziehen. Sie sind derzeit der neueste Verriegelungsmechanismus in Java. Der Synchronisierungsmechanismus ist schwerer als die Klassen java.util.concurrent.
Das Beispiel würde ungefähr so aussehen:
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Sample { private final Lock lock = new ReentrantLock(); private String message = null; public void newmsg(String msg) { lock.lock(); try { message = msg; } finally { lock.unlock(); } } public String getmsg() { lock.lock(); try { String temp = message; message = null; return temp; } finally { lock.unlock(); } } }
quelle
In diesem einfachen Beispiel können Sie in beiden Methodensignaturen einfach
synchronized
als Modifikator nach setzenpublic
.Komplexere Szenarien erfordern andere Dinge.
quelle
Verwenden Sie das
synchronized
Schlüsselwort.class sample { private String msg=null; public synchronized void newmsg(String x){ msg=x; } public synchronized string getmsg(){ String temp=msg; msg=null; return msg; } }
Die Verwendung des
synchronized
Schlüsselworts für die Methoden erfordert Threads, um eine Sperre für die Instanz von zu erhaltensample
. Wenn sich also ein Thread in befindetnewmsg()
, kann kein anderer Thread die Instanz von sperrensample
, selbst wenn er versucht, sie aufzurufengetmsg()
.Auf der anderen Seite kann die Verwendung von
synchronized
Methoden zu einem Engpass werden, wenn Ihre Methoden lang laufende Vorgänge ausführen. Alle Threads müssen warten, auch wenn sie andere Methoden in diesem Objekt aufrufen möchten, die verschachtelt werden könnten.IMO, in Ihrem einfachen Beispiel ist es in Ordnung, synchronisierte Methoden zu verwenden, da Sie tatsächlich zwei Methoden haben, die nicht verschachtelt werden sollten. Unter anderen Umständen kann es jedoch sinnvoller sein, ein Sperrobjekt zum Synchronisieren zu haben, wie in der Antwort von Joh Skeet gezeigt.
quelle
Wenn Sie bei einer anderen Gelegenheit eine Sammlung anstelle eines Strings synchronisieren, iterieren Sie möglicherweise über die Sammlung und befürchten, dass sie mutiert, bietet Java 5 Folgendes:
CopyOnWriteArrayList
CopyOnWriteArraySet
quelle