lockObject上的同步和使用此锁作为锁之间有什么区别?
我知道同步方法和同步块之间的区别,但我不确定关于同步块部分。
假设我有这个代码
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和使用这个锁作为区别? 对我来说似乎是一样的..
当你决定使用同步块时,你如何决定哪个对象是锁?
我个人几乎从来没有locking“这个”。 我通常locking一个私人持有的参考,我知道没有其他代码将被locking。 如果你locking“this”,那么知道你的对象的任何其他代码可能会selectlocking它。 虽然不太可能发生,但它肯定会发生,并可能导致死锁,或者过度locking。
关于你所locking的东西没有什么特别的魔力 – 你可以把它当作一个令牌来有效地考虑。 任何使用相同标记locking的人都将尝试获取相同的locking。 除非您希望其他代码能够获取相同的锁,否则请使用私有variables。 我也鼓励你做final
的variables – 我不记得我曾经想在对象的生命周期中改变锁variables的情况。
我在阅读Java Concurrency In Practice时遇到了同样的问题,我想我会对Jon Skeet和spullara提供的答案增加一些新的观点。
下面是一些示例代码,当doStuff(ValueHolder)
方法执行时,甚至会阻塞“快速” setValue(int)
/ getValue()
方法。
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 } } }
使用this
同步的缺点是其他类可以同步对你的类的引用(当然不是this
)。 在locking对象的引用时恶意或无意使用synchronized
关键字可能会导致类在并发使用情况下performance不佳,因为外部类可以有效地阻止this
同步的方法,并且在您的类中没有任何东西可以做禁止在运行时间。 为了避免这个潜在的隐患,你可以在private final Object
上进行同步,或者使用java.util.concurrent.locks
的Lock
接口。
对于这个简单的例子,你可以交替使用AtomicInteger
而不是同步setter / getter。
有效的Java第二版的项目67是避免过度同步,因此我会同步私人locking对象。
Java中的每个对象都可以充当监视器。 select一个取决于你想要的粒度。 select“this”具有其他类别也可以在同一监视器上同步的优点和缺点。 我的build议是避免直接使用synchronize关键字,而是使用java.util.concurrency库中的更高层次的结构,并具有定义良好的语义。 本书从非常着名的专家那里得到了很多很好的build议:
Java并发实践http://amzn.com/0321349601
在这种情况下,selectlocking哪个对象并不重要。 但是您必须始终使用相同的对象进行locking才能实现正确的同步。 上面的代码并不能保证正确的同步,因为你曾经使用'this'对象作为锁,然后使用'lockObject'作为锁。