【问题标题】:How to specify an object to be locked in java using Lock如何使用Lock在java中指定要锁定的对象
【发布时间】:2014-09-25 04:44:21
【问题描述】:

使用 synchronized(intrinsic locking) 关键字进行锁定,我们可以这样做:

public void addSum(int a) {
   synchronized(q) {
     q.add(a); // q is say a Queue
   }
}

在上面的代码中,当一个对象试图调用 addSum() 方法,即 x.addSum(10) 时,锁将被保持在 'q' 而不是 x。所以使用同步我们可以锁定一个不是实际调用对象(类)的对象。

下面我使用的是 java concurrent 包中的 Lock,有没有办法指定应该锁定哪个对象(即在上面的代码 sn-p 中使用同步它指定了锁定/同步应该打开'q')。但是下面当我使用锁时,我没有指定锁应该在哪个对象上。能做到吗?

public void addSum(int a) {
   lock.tryLock();
   q.add(a);
   lock.unlock();
 }

我确实提到了 - http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html。但是正在寻找更小的例子来清除我的概念。

【问题讨论】:

    标签: java multithreading concurrency


    【解决方案1】:

    不,Lock 对象的工作方式与 synchronized 不同。 synchronized 不能在方法调用内开始并到达该方法调用之外。你展示的图案

    lock.tryLock();
    q.add(a);
    lock.unlock();
    

    只有在相反的情况下才有可能。 Lock 对象通常通过原子地打开/关闭开关/标志来工作,表明它们已经获得或释放了锁。

    【讨论】:

    • 哦,当我说 q.add(a) 它实际上并没有调用自己。它是队列中的添加方法。我将另一个方法名称更改为 addSum。所以我展示的用于同步的代码sn-p实际上并没有以不同的方法开始和结束。
    • 那么当我在上面的代码中使用 Lock 时,sn-p 它锁定了哪个对象?如果同步代码 sn-p 它锁定在“q”上。
    • @srock 第一条评论:synchronized 在语法上作为 代码块 工作,可以嵌套在方法中,也可以跨越整个方法。您在块的开头获取锁并在结束时释放它。然而,Lock 对象的锁可以跨越多个代码块,进出方法调用,并且可能(危险地)永远不会被释放。
    • @srock 第二条评论:这取决于实现。以ReentrantLock 为例,它不会锁定 任何东西。它使用一种称为 compare-and-swap 的技术自动设置一个标志,指示特定线程作为所有者。
    • 第一条评论回复同意。第二条评论:所以我的理解是这取决于它是哪种类型的锁。
    【解决方案2】:

    我想你误解了“锁”这个词的意思。假设调用了这个方法:

    void foobar() {
        synchronized(x) {
            y.doSomething();
        }
    }
    

    我们说x 在线程处于y.doSomething() 调用中时被“锁定”,但这不会阻止其他线程访问或更新x 的字段。 synchronized 关键字意味着一件事,而且只有一件事。

    JVM 不允许两个线程同时在同一个对象上同步。

    这就是全部的意思。你如何使用它取决于你。我的示例是使用它来防止y.doSomething() 同时在多个线程中被调用,但它仅在对y.doSomething() 的每次调用都以相同方式保护时才有效,并且仅在x 始终有效时才有效指的是同一个对象。

    java.util.concurrent.ReentrantLock 类的工作方式大致相同。 JVM 做出的唯一保证是没有两个线程可以同时“锁定”同一个 ReentrantLock 对象。这就是它所做的一切。剩下的就看你自己了。


    P.S.,您的第二个示例未测试 lock.tryLock() 返回的值。这是一个错误。如果lock.tryLock()返回false,表示锁失败。

    【讨论】:

    • 完美。最后你提到我没有检查lock.try lock()返回的布尔值,所以在我上面发布的代码sn-p中,如果锁不可用,线程仍然会尝试将整数添加到队列中'q'?那是对的吗。所以基本上它会添加到队列'q'而不考虑锁定对象?
    猜你喜欢
    • 1970-01-01
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多