【问题标题】:Java synchronized blocks -- lock objectsJava同步块——锁对象
【发布时间】:2013-08-09 23:06:32
【问题描述】:

在示例代码中

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 页面上,

lock1lock2 控制着 c1c2 响应的更新。

然而,

    synchronized(lock2) 

正在获取对象lock1的锁,并在同步块时释放它

    synchronized(lock1) {
        c1++;
    }

被执行。

当这个块被执行时,可能有 this 对象的成员 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?

在其他一些讨论中。

【问题讨论】:

  • 为什么你认为synchronized(lock2) 锁定了lock1
  • 我熟悉并发文档,只是阅读了该页面。它没有说synchronized(lock2) 锁定lock1,因为它没有。
  • 这通常是同步块的工作方式—— synchronize(someStuff) 获取 someStuff 的锁,因此在线程完成执行该块之前没有其他人可以访问 someStuff。阅读页面。
  • @Roam:不,你错了。检查我更新的答案。

标签: java synchronized


【解决方案1】:

实施 1.

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

实施 2.

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

实施 3.

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

【讨论】:

  • 据我所知,你的第一个标准杆。验证我在说什么。那么,该实施的意义何在?仅获得 lock1 的锁,而 c1 仍处于“松散”状态。 “实施1”如何 - 你在你的ans中所说的方式。与“实施 2”不同?
  • 当你有多个锁时,区别就出现了——实现1允许一个线程锁定lock1,但另一个线程能够锁定lock2。两个线程也可能在这里死锁 - 如果线程“A”拥有lock1,线程“B”拥有lock2,但是线程“A”想要锁定lock2,而线程“B”想要锁定lock1。在实现 2 中,只有 1 个锁,因此这里不可能出现死锁。但是如果正在执行另一个synchronized 方法,则一个线程不能执行一个synchronized 方法;锁被持有。
  • 在这种情况下,我可以有另一种方法 public void decr1() { c1--; } 在同一个班。所以在这种情况下,decr1() 可以在 incr1 由其他线程(?)运行时执行和更新 c1,因为它是锁定的 lock1,而不是 c1。不是吧?
  • 如果您要添加一个在c1 上运行的decr1 方法,那么让它锁定在lock1(与incr1 使用相同的锁定对象),所以两个线程不能使用任一方法同时更新c1
  • 感谢有用的答案。解释 lock1/lock2 的意图。
【解决方案2】:

在不指定锁对象的情况下标记块或方法synchronized会在拥有该方法的对象上同步;在这种情况下,MsLunch 实例。相当于synchronized(this)。 lock-object 习惯用法的目的是打破锁定,以便可以分别操作c1c2synchronized 块只能在对象上同步,不能在原语上同步。

【讨论】:

    【解决方案3】:
    synchronized(lock2){
      // do sth
    }
    

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

    在哪里

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

    在此对象上获取对象。

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

    【讨论】:

    【解决方案4】:

    据我所知,您的说法不正确。您链接的页面也没有说明您在问题中声称的内容。这就是锁的工作原理:锁完全阻止线程访问对象。锁只能防止另一个线程获取相同的锁,而另一个线程已经获取了该锁。

    这意味着这可能发生:

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

    【讨论】:

    • 正确,它们是一样的。这意味着在给定的对象实例中,所有同步的代码(方法上的块或关键字)都锁定在同一个锁定对象上。如果这不是您想要/需要的,请使用不同的锁定对象作为同步块的参数。
    • @Roam:他所写的事实是正确的,尽管最初的措辞有些不足。
    • 我的回答一点也不假。我只是告诉你真相。 :)
    • 我想我现在会保持原样。所以请随意阅读:)我知道,“谎言”可能是一个错误的词选择,绝对不是人身攻击,而是更普遍的事实。
    • 在阅读您的cmets到其他问题时,我认为您仍然没有完全理解我写的第一部分。这是另一个澄清的尝试:使用同步块会影响其他同步块的行为(实际上没有其他影响)。这是编写多线程应用程序时要掌握的关键。同步代码不会阻止其他非同步代码执行或访问锁定的对象。
    【解决方案5】:

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

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

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

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

    static ReentrantLock lock = new ReentrantLock();
    for(;;){
      lock.lock();
      ...
      lock.unlock();
    }
    

    【讨论】:

      猜你喜欢
      • 2013-04-25
      • 1970-01-01
      • 1970-01-01
      • 2012-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-11
      • 1970-01-01
      相关资源
      最近更新 更多