在lockObject上同步和使用this作为锁有什么区别?
我知道同步方法和同步块之间的区别,但我不确定同步块部分。
假设我有这段代码
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);
}
}
在这种情况下使用 lockObject 和使用 this 作为锁有什么区别?这对我来说似乎是一样的。
当你决定使用同步块时,你如何决定哪个对象是锁?
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 lockObject and using this as the lock? It seems to be the same to me..
When you decide to use synchronized block, how do you decide which object to be the lock?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
就我个人而言,我几乎从不锁定“这个”。我通常锁定一个私人持有的引用,我知道没有其他代码会锁定该引用。如果您锁定“this”,那么了解您的对象的任何其他代码都可能会选择锁定它。虽然这种情况不太可能发生,但它肯定会发生——并且可能导致死锁,或者只是过度锁定。
你锁定的东西并没有什么特别神奇的地方——你可以有效地将它视为一个令牌。任何使用相同令牌锁定的人都会尝试获取相同的锁。除非您希望其他代码能够获取相同的锁,否则请使用私有变量。我也鼓励您将变量
final
- 我不记得我曾经曾经想要换锁的情况对象生命周期内的变量。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 any other 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.
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 want other code to be able to acquire the same lock, use a private variable. I'd also encourage you to make the variable
final
- I can't remember a situation where I've ever wanted to change a lock variable over the lifetime of an object.当我阅读《Java 并发实践》时,我也遇到了同样的问题,我想我应该对 Jon Skeet 和 spullara 提供的答案添加一些补充观点。
下面是一些示例代码,当
doStuff(ValueHolder)
方法执行时,它们甚至会阻塞“快速”的setValue(int)
/getValue()
方法。使用
this
进行同步的缺点是其他类可以在对您的类的引用上进行同步(当然不是通过this
)。在锁定对象引用时恶意或无意地使用synchronized
关键字可能会导致您的类在并发使用下表现不佳,因为外部类可以有效地阻止您的this
-synchronized方法,并且您无法(在您的类中)执行任何操作来在运行时禁止这种情况。为了避免这种潜在的陷阱,您可以在私有最终对象
上进行同步,或者使用java.util.concurrent.locks
中的Lock
接口。对于这个简单的示例,您可以交替使用
AtomicInteger
而不是同步 setter/getter。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.
Here's some example code which will block even the "quick"
setValue(int)
/getValue()
methods while thedoStuff(ValueHolder)
method executes.The downside of using
this
for synchronization is other classes can synchronize on a reference to your class (not viathis
, of course). Malicious or unintentional use of thesynchronized
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 yourthis
-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 aprivate final Object
or use theLock
interface injava.util.concurrent.locks
.For this simple example, you could alternately use an
AtomicInteger
rather than synchronizing the setter/getter.Effective Java Second Edition 的第 67 项是避免过度同步,因此我会在私有锁对象上同步。
Item 67 of Effective Java Second Edition is Avoid excessive synchronization, thus I would synchronize on a private lock object.
Java 中的每个对象都可以充当监视器。选择一种取决于您想要的粒度。选择“this”的优点和缺点是其他类也可以在同一监视器上同步。不过,我的建议是避免直接使用 Synchronize 关键字,而是使用 java.util.concurrency 库中的结构,这些结构更高级别并且具有明确定义的语义。这本书中有很多来自著名专家的好建议:
Java Concurrency in Practice
http://amzn.com/0321349601
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 Concurrency in Practice
http://amzn.com/0321349601
在这种情况下,选择哪个对象作为锁定并不重要。但您必须始终使用相同的对象进行锁定才能实现正确的同步。上面的代码不能确保正确的同步,因为您曾经使用“this”对象作为锁,然后使用“lockObject”作为锁。
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.