java - 同步 - 如何在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 之后。

更复杂的场景需要其他的东西。

...