什么情况下需要在Java中同步方法访问?
在什么情况下需要同步对实例成员的访问? 我知道对类的静态成员的访问总是需要进行同步 - 因为它们是在类的所有对象实例之间共享的。
我的问题是如果我不同步实例成员,我什么时候会不正确?
例如,如果我的课是
public class MyClass {
private int instanceVar = 0;
public setInstanceVar()
{
instanceVar++;
}
public getInstanceVar()
{
return instanceVar;
}
}
在什么情况下(使用类MyClass
)我需要有方法: public synchronized setInstanceVar()
和public synchronized getInstanceVar()
?
预先感谢您的答案。
这取决于你是否希望你的课程是线程安全的。 大多数类不应该是线程安全的(为简单起见),在这种情况下,您不需要同步。 如果你需要它是线程安全的,你应该同步访问或使变量易变。 (它避免了其他线程获取“陈旧”数据。)
synchronized
修饰符是一个坏主意,应该不惜一切代价避免。 我认为,Sun试图让锁定变得更容易达到令人赞叹,但synchronized
只会导致更多的麻烦而不值得。
问题是,一个synchronized
方法实际上是获取上的锁只是语法糖this
并保持该方法的持续时间。 因此, public synchronized void setInstanceVar()
将相当于这样的事情:
public void setInstanceVar() {
synchronized(this) {
instanceVar++;
}
}
这有两个原因是不好的:
synchronized
方法使用完全相同的锁,这会降低吞吐量 没有什么能够阻止我在另一个班级做这样的事情:
MyClass c = new MyClass();
synchronized(c) {
...
}
在该synchronized
块中,我持有MyClass
所有synchronized
方法所需的锁。 这进一步降低了吞吐量,并大大增加了死锁的可能性。
更好的方法是有一个专用lock
对象并直接使用synchronized(...)
块:
public class MyClass {
private int instanceVar;
private final Object lock = new Object(); // must be final!
public void setInstanceVar() {
synchronized(lock) {
instanceVar++;
}
}
}
或者,您可以使用java.util.concurrent.Lock
接口和java.util.concurrent.locks.ReentrantLock
实现来获得基本相同的结果(实际上,它在Java 6中是相同的)。
如果你想让这个类的线程安全,我会声明instanceVar
为volatile
,以确保始终获得来自内存的最新值,并且还会使setInstanceVar()
synchronized
因为在JVM中,增量不是原子操作。
private volatile int instanceVar =0;
public synchronized setInstanceVar() { instanceVar++;
}
链接地址: http://www.djcxy.com/p/76267.html