在示例代码中
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
在this页上,
lock1 和 lock2 正在控制 c1 和 c2 上的更新。
然而,
synchronized(lock2)
正在获取对象 lock1 的锁定,并在同步块
时释放它 synchronized(lock1) {
c1++;
}
已执行。
正在执行此块时,可能会有 此对象的成员 c1 的更新仍然 - 我不这样做 了解如何防止此更新 与代码中的 lock1 同步。
对象 lock1 有独占访问权限 - 没有别的(?)
那么,实现如何
public void inc1() {
synchronized(lock1) {
c1++;
}
}
在上面的代码中与
不同public void synchronized inc1() {
c1++;
}
甚至
public void inc1() {
synchronized(c1) {
//do something on c1
}
}
当 c1 是一个对象但不是一个原语?
我在这里缺少什么?
注意:我看到了
What is the difference between synchronized on lockObject and using this as the lock?
和
Java synchronized method lock on object, or method?
在其他一些讨论中。
答案 0 :(得分:6)
实施1。
您正在锁定lock1
对象。其他任何需要锁定的lock1
都无法执行。让两个方法锁定不同的对象意味着这两个方法可以并发运行,但没有两个线程可以同时运行相同的方法。
实施2。
创建方法synchronized
意味着整个方法体隐式位于synchronized(this)
块中(如果方法为Class
,则在static
对象上同步。如果两者都是方法是synchronized
,然后一个方法会阻止另一个方法同时运行,这与将两个方法锁定在不同对象上的方法不同。
实施3。
如果c1
是一个对象而不是一个原语,那么语义与实现1非常相似 - 锁定一个显式对象。
答案 1 :(得分:0)
据我所知,您的陈述不正确。您链接的页面并未说明您在问题中声明的内容。这就是锁的工作方式:锁不根本不会阻止访问对象的线程。锁只会阻止获取同一锁的另一个线程,而另一个线程已经获得该锁。
这意味着可能发生这种情况:
Thread A: synchronize (lockObject)
Thread B: lockObject.toString();
Thread A: release the lock on lockObject
当两个线程同时想要相同的锁时会发生这种情况:
Thread A: synchronize (lockObject)
Thread B: synchronize (lockObject) // This will block until (1) !
Thread A: do some stuff and then release lock on lockObject
Thread B: gets the lock (1)
然而:
public void synchronized inc1() {
c1++;
}
与:
完全相同public void inc1() {
synchronized(this) {
c1++;
}
}
答案 2 :(得分:0)
在没有指定锁定对象的情况下标记块或方法synchronized
在拥有该方法的对象上进行同步;在这种情况下,MsLunch
实例。它相当于synchronized(this)
。锁定对象习惯用法的目的是打破锁定,以便可以单独操作c1
和c2
。 synchronized
块只能在对象上同步,而不能在基元上同步。
答案 3 :(得分:0)
synchronized(lock2){
// do sth
}
实际上是获取对象lock2的锁定
其中
public void synchronized inc1() {
c1++;
}
获取此对象的对象。
一旦程序离开块,将释放synchronized获取的锁。
答案 4 :(得分:0)
我遇到一个阻碍锁定的线程
for(;;){synchronized(lockObject){
...
}}
我想Java不想在第一次机会时自行解锁它。
使用java.util.concurrent.locks.ReentrantLock修复了问题
static ReentrantLock lock = new ReentrantLock();
for(;;){
lock.lock();
...
lock.unlock();
}