Java 在 lockObject 上同步和使用 this 作为锁有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3369287/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the difference between synchronized on lockObject and using this as the lock?
提问by GantengX
I know the difference between synchronized method and synchronized block but I am not sure about the synchronized block part.
我知道同步方法和同步块之间的区别,但我不确定同步块部分。
Assuming I have this code
假设我有这个代码
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);
}
}
In this case what is the difference between using lockObjectand using thisas the lock? It seems to be the same to me..
在这种情况下,使用lockObject和使用this作为锁有什么区别?好像跟我一样。。
When you decide to use synchronized block, how do you decide which object to be the lock?
当您决定使用同步块时,您如何决定将哪个对象作为锁?
采纳答案by Jon Skeet
Personally I almost never lock on "this". I usually lock on a privately held reference which I know that no other code is going to lock on. If you lock on "this" then anyother code which knows about your object might choose to lock on it. While it's unlikely to happen, it certainly could do - and could cause deadlocks, or just excessive locking.
就我个人而言,我几乎从不锁定“这个”。我通常锁定一个私有引用,我知道没有其他代码会锁定它。如果您锁定“this”,那么任何了解您的对象的其他代码都可能选择锁定它。虽然它不太可能发生,但它肯定会发生 - 并且可能导致死锁,或者只是过度锁定。
There's nothing particularly magical about what you lock on - you can think of it as a token, effectively. Anyone locking with the same token will be trying to acquire the same lock. Unless you wantother code to be able to acquire the same lock, use a private variable. I'd alsoencourage you to make the variable final
- I can't remember a situation where I've everwanted to change a lock variable over the lifetime of an object.
你锁定的东西没有什么特别神奇的——你可以把它想象成一个有效的标记。使用相同令牌锁定的任何人都将尝试获取相同的锁定。除非您希望其他代码能够获取相同的锁,否则请使用私有变量。我还鼓励您创建变量final
- 我不记得我曾经想在对象的生命周期内更改锁定变量的情况。
回答by Gopi
In this case it does not matter which object you choose for lock. But you must consistently use the same object for locking to achieve correct synchronization. Above code does not ensure proper synchronization as you once use the 'this' object as lock and next the 'lockObject' as lock.
在这种情况下,您选择锁定哪个对象并不重要。但是您必须始终使用相同的对象进行锁定以实现正确的同步。上面的代码不能确保正确的同步,因为您曾经使用“this”对象作为锁,然后使用“lockObject”作为锁。
回答by Manuel Selva
Item 67 of Effective Java Second Editionis Avoid excessive synchronization, thus I would synchronize on a private lock object.
Effective Java Second Edition 的第 67 项是避免过度同步,因此我会在私有锁对象上进行同步。
回答by Sam Pullara
Every object in Java can act as a monitor. Choosing one is dependent on what granularity you want. Choosing 'this' has the advantage and disadvantage that other classes could also synchronize on the same monitor. My advice though is to avoid using the synchronize keyword directly and instead use constructs from the java.util.concurrency library which are higher level and have well defined semantics. This book has a lot of great advice in it from very notable experts:
Java 中的每个对象都可以充当监视器。选择一个取决于您想要的粒度。选择“this”的优点和缺点是其他类也可以在同一监视器上同步。不过,我的建议是避免直接使用同步关键字,而是使用来自 java.util.concurrency 库的更高级别且具有明确定义语义的构造。这本书中有很多来自非常著名的专家的很好的建议:
Java Concurrency in Practice http://amzn.com/0321349601
Java 并发实践 http://amzn.com/0321349601
回答by Phil M
I had this same question when I was reading Java Concurrency In Practice, and I thought I'd add some added perspective on the answers provided by Jon Skeet and spullara.
我在阅读 Java Concurrency In Practice 时遇到了同样的问题,我想我会对 Jon Skeet 和 spullara 提供的答案添加一些额外的观点。
Here's some example code which will block even the "quick" setValue(int)
/getValue()
methods while the doStuff(ValueHolder)
method executes.
下面是一些示例代码,它们甚至会在方法执行时阻止“快速” 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
}
}
}
The downside of using this
for synchronization is other classes can synchronize on a reference to your class (not via this
, of course). Malicious or unintentional use of the synchronized
keyword while locking on your object's reference can cause your class to behave poorly under concurrent usage, as an external class can effectively block your this
-synchronized methods and there is nothing you can do (in your class) to prohibit this at runtime. To avoid this potential pitfall, you would synchronize on a private final Object
or use the Lock
interface in java.util.concurrent.locks
.
this
用于同步的缺点是其他类可以在对您的类的引用上进行同步(this
当然不是通过)。synchronized
在锁定对象的引用时恶意或无意使用关键字会导致类在并发使用下表现不佳,因为外部类可以有效地阻止您的this
-synchronized 方法,并且您无能为力(在您的类中)禁止这种情况在运行时。为了避免这种潜在的危险,你会在同步private final Object
或使用该Lock
接口java.util.concurrent.locks
。
For this simple example, you could alternately use an AtomicInteger
rather than synchronizing the setter/getter.
对于这个简单的示例,您可以交替使用AtomicInteger
而不是同步 setter/getter。