将synchronized()与ReentrantLock.lock()混合

时间:2010-05-24 23:38:05

标签: java locking synchronized reentrancy

在Java中,ReentrantLock.lock()ReetrantLock.unlock()使用与synchronized()相同的锁定机制吗?

我的猜测是“不”,但我希望是错的。

示例:

想象一下,线程1和线程2都可以访问:

ReentrantLock lock = new ReentrantLock();

线程1运行:

synchronized (lock) {
    // blah
}

线程2运行:

lock.lock();
try {
    // blah
}
finally {
    lock.unlock();
}

假设线程1首先到达其部分,然后在线程1完成之前到达线程2:线程2将等待线程1离开synchronized()块,还是继续运行?

3 个答案:

答案 0 :(得分:14)

不,即使线程1在同一lock()synchronized,线程2也可lock。这就是documentation所说的:

  

请注意,Lock实例只是   正常的对象,可以自己   用作同步中的目标   声明。获取显示器锁定   一个Lock实例没有指定   与调用任何一个的关系   该实例的lock()方法。它   建议避免混淆   你永远不会在这里使用Lock实例   方式,除了他们自己   实施

答案 1 :(得分:9)

这两种机制是不同的。实施/绩效明智:

  • 同步机制使用“内置于”JVM中的锁定机制;底层机制受特定JVM实现的约束,但通常使用原始compare-and-set operation(CAS)指令的组合,用于没有争用锁的情况加上操作系统提供的底层锁定机制;
  • 诸如ReentrantLock之类的锁类基本上是用纯Java编写的(通过Java 5中引入的库,它将CAS指令和线程去调度暴露给Java),因此在操作系统中更加标准化,更可控(见下文)。 / LI>

在某些情况下,显式锁可以更好地执行。如果你看一下我在Java 5下执行的这个comparison of locking mechanisms,你会看到在那个特定的测试中(多个线程访问一个数组),在“不公平”模式下配置的显式锁类(黄色和青色三角形)允许比普通同步(紫色箭头)更多的吞吐量。

(我还应该说,在最新版本的Hotspot中,synchronized的性能得到了提升;在最新版本或其他情况下可能没有太多内容 - 这显然是在一个环境中的一个测试。 )

功能明智:

  • 同步机制提供最少的功能(你可以锁定和解锁,锁定是一个全有或全无的操作,你更依赖OS编写者决定的算法),虽然具有内置语法的优点以及JVM内置的一些监控;
  • 显式锁类提供更多控制,特别是你可以指定一个“公平”锁定,锁定超时,如果你需要改变锁定的行为,则覆盖......

答案 2 :(得分:0)

为什么在Account类中使余额保持静态? 删除静电,它应该工作。

另外,对您的线程使用情况有疑问。在TestMain中,您可以创建新线程并分配可运行的内容,例如WithdrawRequests& DepositRequests。但是,您再次在这些可运行的构造函数中创建新线程。这将导致run方法执行两次!