1

在示例代码中

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++;
    }
}
}

这个页面上,

lock1lock2正在控制c1c2响应的更新。

然而,

    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是对象而不是原始对象时?

我在这里想念什么?

注:我看到了

在 lockObject 上同步和使用它作为锁有什么区别?

Java同步方法锁定对象还是方法?

在其他一些讨论中。

4

5 回答 5

7

实施 1。

您正在锁定lock1对象。没有其他需要锁定的东西lock1可以执行。让你的两个方法锁定不同的对象意味着这两个方法可以同时运行,但没有两个线程可以同时运行同一个方法。

实施 2。

创建一个方法synchronized意味着整个方法体隐式在一个块中(如果方法是 ,则在对象synchronized(this)上同步。如果两个方法都是,那么一个方法会阻止另一个方法同时运行,这与锁定两者不同不同对象的方法。Classstaticsynchronized

实施 3。

如果c1是对象而不是原语,则语义与实现 1 非常相似——锁定显式对象。

于 2013-08-09T23:14:11.270 回答
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++;
    }
}
于 2013-08-09T23:11:50.373 回答
0

在不指定锁对象的情况下标记块或方法synchronized会在拥有该方法的对象上同步;在这种情况下,MsLunch实例。它相当于synchronized(this). c1锁定对象习语的目的是打破锁定,以便c2可以单独操作。synchronized块只能在对象上同步,不能在原语上同步。

于 2013-08-09T23:13:29.283 回答
0
synchronized(lock2){
  // do sth
}

实际上是在获取对象 lock2 的锁

然而

public void synchronized inc1() {
        c1++;
}

在此对象上获取对象。

程序离开块后,同步获取的锁将被释放。

于 2013-08-09T23:14:04.240 回答
0

我遇到了一个线程占用锁的问题

for(;;){synchronized(lockObject){
...
}}

我猜Java不喜欢一有机会就自己解锁它。

使用 java.util.concurrent.locks.ReentrantLock 解决了这个问题

static ReentrantLock lock = new ReentrantLock();
for(;;){
  lock.lock();
  ...
  lock.unlock();
}
于 2017-01-02T20:26:29.813 回答