[英]How to synchronize or lock upon variables in Java?
讓我用這個小而簡單的樣本:
class Sample {
private String msg = null;
public void newmsg(String x){
msg = x;
}
public String getmsg(){
String temp = msg;
msg = null;
return temp;
}
}
我們假設函數newmsg()
由我無權訪問的其他線程調用。
我想使用synchonize方法來保證字符串msg
每次僅由一個函數使用。 換句話說,函數newmsg()
不能與getmsg()
同時運行。
這很簡單:
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;
}
}
}
請注意,我也沒有讓自己的同步方法或同步this
。 我堅信只有你的代碼可以訪問的對象才能獲得鎖,這是個好主意,除非你故意暴露鎖。 這樣可以更容易地讓自己放心,沒有其他任何東西會以與代碼不同的順序獲取鎖定等。
對於此功能,最好不要使用鎖。 嘗試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);
}
}
不需要鎖,代碼更簡單恕我直言。 在任何情況下,它都使用標准結構,它可以滿足您的需求。
從Java 1.5開始,考慮java.util.concurrent包總是一個好主意。 它們現在是java中最先進的鎖定機制。 同步機制比java.util.concurrent類更重要。
該示例看起來像這樣:
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();
}
}
}
在這個簡單的示例中,您可以在兩個方法簽名中將synchronized
作為修飾符放在public
之后。
更復雜的場景需要其他東西。
使用synchronized
關鍵字。
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;
}
}
在方法上使用synchronized
關鍵字將要求線程獲取對sample
實例的鎖定。 因此,如果任何一個線程都在newmsg()
,那么即使它試圖調用getmsg()
,也沒有其他線程能夠對sample
實例進行鎖定。
另一方面,如果您的方法執行長時間運行操作,使用synchronized
方法可能會成為瓶頸 - 所有線程,即使他們想要調用該對象中可能交錯的其他方法,仍然需要等待。
IMO,在你的簡單例子中,可以使用synchronized方法,因為你實際上有兩個不應該交錯的方法。 但是,在不同的情況下,讓一個鎖定對象同步更有意義,如Joh Skeet的回答所示。
如果在另一個場合你正在同步一個Collection而不是一個String,也許你正在迭代這個集合,並擔心它會發生變異,Java 5提供:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.