Gan*_*ngX 47 java concurrency locking synchronized synchronized-block
我知道同步方法和同步块之间的区别,但我不确定同步块部分.
假设我有这个代码
class Test {
private int x=0;
private Object lockObject = new Object();
public void incBlock() {
synchronized(lockObject) {
x++;
}
System.out.println("x="+x);
}
public void incThis() { // same as synchronized method
synchronized(this) {
x++;
}
System.out.println("x="+x);
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,使用lockObject和使用它作为锁有什么区别?对我来说似乎是一样的..
当您决定使用synchronized块时,如何确定哪个对象是锁?
Jon*_*eet 64
就个人而言,我几乎从不锁定"这个".我通常会锁定一个私有的引用,我知道没有其他代码可以锁定.如果您锁定"this",那么知道您的对象的任何其他代码可能会选择锁定它.虽然它不太可能发生,但它当然可以 - 并且可能导致死锁,或者只是过度锁定.
关于你锁定什么并没有什么特别神奇的 - 你可以有效地将它视为一种象征.任何使用相同令牌锁定的人都将尝试获取相同的锁.除非您希望其他代码能够获取相同的锁,否则请使用私有变量.我也鼓励你把这些变量final-我不记得的情况下,我曾经想在对象的生命周期改变锁变量.
Phi*_*l M 12
当我阅读Java Concurrency In Practice时,我有同样的问题,我想我会在Jon Skeet和spullara提供的答案上添加一些额外的观点.
这是一些示例代码,它将在方法执行时阻止"快速" setValue(int)/ getValue()方法doStuff(ValueHolder).
public class ValueHolder {
private int value = 0;
public synchronized void setValue(int v) {
// Or could use a sychronized(this) block...
this.value = 0;
}
public synchronized int getValue() {
return this.value;
}
}
public class MaliciousClass {
public void doStuff(ValueHolder holder) {
synchronized(holder) {
// Do something "expensive" so setter/getter calls are blocked
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用this同步的缺点是其他类可以同步对类的引用(this当然不是通过).synchronized在锁定对象的引用时恶意或无意使用关键字会导致您的类在并发使用情况下表现不佳,因为外部类可以有效地阻止您的this同步方法,并且您无法在您的类中执行任何操作来禁止此操作在运行时.为避免这种潜在的陷阱,您可以同步private final Object或使用Lock界面java.util.concurrent.locks.
对于这个简单的例子,您可以交替使用AtomicInteger而不是同步setter/getter.
Effective Java Second Edition的第67项是避免过度同步,因此我将在私有锁对象上进行同步.
| 归档时间: |
|
| 查看次数: |
33180 次 |
| 最近记录: |