【问题标题】:How implementation of Re-entrant lock and Synchronization is different重入锁和同步的实现有何不同
【发布时间】:2017-03-26 14:43:21
【问题描述】:

根据java源码

ReentrantLock 的锁(非公平)如下。

public boolean lock(){
      int c=getState();
      if(c==0){
         compareAndSetState(0,1);
      }
}
//getState method
public int getState(){
    return state;
}
public boolean compareAndSetState(int expected,int update){
    unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

stateOffSet 的值是 state 在内存中的偏移量(使用反射)。

我从上面的代码可以理解的是,当我们调用 lock.lock() 时,state 字段的第一个值在内存中检查,如果它为零,那么只有锁被赋予调用线程.

所以我的问题是当我们使用同步关键字时会发生什么?在 Synchronized 中是否也检查并设置了一些锁定字段?

还有一个疑问,我在某处读到可重入锁允许多个等待队列,这是什么意思?我们不是只有一个队列吗?

【问题讨论】:

  • "(使用反射)" - 不,没有使用反射。它在这里没有用,而且太慢了。要了解同步的工作原理,只需阅读有关同步工作原理的教程。不,实现与 ReentrantLock 不同,尽管它确实实现了许多非常相似的目标,但不是所有目标(如果有,就不需要 ReetrantLock)
  • 根据 grepcode 我可以看到 stateOffset = unsafe.objectFieldOffset (AbstractQueuedSynchronizer.class.getDeclaredField("state"));当然 ReentrantLock 比我写的要多得多,但是我在 ReentrantLock 状态值的问题决定,是锁可用还是被其他线程锁定。在 Synchronized 中会发生什么?我找不到给出它的任何链接,当我们使用 Synchronized 时 jvm 内部会做什么。

标签: java reflection concurrency locking reentrantlock


【解决方案1】:

可重入锁允许多个等待队列,这是什么意思?

这意味着您可以从ReentrantLock 对象中获得多个Condition 对象。当线程想要等待受锁保护的东西的原因不止一个时,这很有用。

一个典型的例子是多生产者、多消费者队列。您可以有一个Condition 供消费者用来等待队列变为非空,而另一个Condition 供生产者用来等待队列变为非满。那是一种优化。它确保生产者不会唤醒其他等待的生产者,消费者也不会唤醒其他等待的消费者。

如果您使用 synchronized 块保护队列,则无法使用相同的优化,因为 o.wait() 方法无法让线程说出它正在等待什么事件。


当我们使用synchronized 关键字时会发生什么

您唯一可以确定的是您在 Java 语言规范中阅读的内容:不允许两个线程同时在同一个对象上同步、内存可见性影响等。

至于它是如何实现的,……这在不同的架构上会有所不同,也许在不同的操作系统上也会有所不同。在最低级别,它可能类似于ReentrantLock 的工作方式,因为大多数硬件架构提供了大约一种合理的方式来实现它。但是synchronized 实现(如果有)和ReentrantLock 实现使用的中级API 和库的细节可能不同。唯一确定的方法是检查 JVM 和库源代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多