让我使用这个小而简单的样本:
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()
同时运行。
答案 0 :(得分:150)
这很简单:
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
上同步。我坚信只对你的代码才能访问的对象获取锁定是个好主意,除非你故意暴露锁。这样可以更容易地向自己保证,其他任何东西都不会以与代码不同的顺序获取锁定等。
答案 1 :(得分:48)
对于此功能,您最好不要使用锁。试试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);
}
}
无需锁定,代码更简单恕我直言。在任何情况下,它都使用一个符合你想要的标准结构。
答案 2 :(得分:7)
从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();
}
}
}
答案 3 :(得分:2)
在这个简单的示例中,您可以在synchronized
之后将public
作为修饰符添加到两个方法签名中。
更复杂的情况需要其他东西。
答案 4 :(得分:1)
使用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()
中,则其他线程无法锁定sample
的实例,即使它试图调用getmsg()
。
另一方面,如果您的方法执行长时间运行操作,使用synchronized
方法可能会成为瓶颈 - 所有线程,即使他们想要调用该对象中可能交错的其他方法,仍然会有等等。
IMO,在您的简单示例中,可以使用同步方法,因为您实际上有两个不应交错的方法。但是,在不同的情况下,让一个锁定对象同步更有意义,如Joh Skeet的回答所示。
答案 5 :(得分:0)
如果在另一个场合你正在同步一个Collection而不是一个String,那么你可能正在迭代该集合并担心它会发生变异,Java 5提供: