16

在 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()块,还是继续运行?

4

3 回答 3

15

不,lock()即使 Thread 1 位于synchronized同一Thread 2 上,Thread 2 也可以lock。这是文档必须说的:

请注意,Lock 实例只是普通对象,它们本身可以用作同步语句中的目标。获取 Lock 实例的监视器锁与调用该实例的任何 lock() 方法没有指定关系。建议为避免混淆,除非在它们自己的实现中,否则不要以这种方式使用 Lock 实例。

于 2010-05-24T23:40:58.343 回答
9

这两种机制是不同的。实施/性能方面:

  • 同步机制使用“内置”在 JVM 中的锁定机制;底层机制取决于特定的 JVM 实现,但通常使用原始比较和设置操作(CAS) 指令的组合,用于不争用锁的情况以及操作系统提供的底层锁定机制;
  • 诸如 ReentrantLock 之类的锁类基本上是用纯 Java 编码的(通过 Java 5 中引入的库,该库向 Java 公开 CAS 指令和线程调度),因此在操作系统之间更加标准化并且更可控(见下文)。

在某些情况下,显式锁可以执行得更好。如果您查看我在 Java 5 下执行的锁定机制的比较,您会发现在该特定测试(多个线程访问数组)中,以“不公平”模式配置的显式锁定类(黄色和青色三角形)允许更多吞吐量比普通同步(紫色箭头)。

(我还应该说,在较新版本的 Hotspot 中,同步的性能得到了改进;在最新版本或其他情况下可能没有太多改进——这显然是在一个环境中的一项测试。)

功能方面:

  • 同步机制提供了最少的功能(您可以锁定和解锁,锁定是一个全有或全无的操作,您更受操作系统编写者决定的算法的影响),尽管具有内置语法和一些监控的优势内置在JVM中;
  • 显式锁类提供更多控制,特别是您可以指定“公平”锁,锁定超时,如果需要更改锁的行为则覆盖......
于 2010-05-25T02:18:29.510 回答
0

为什么在 Account 类中将余额设为静态?去除静电,它应该可以工作。

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

于 2011-05-03T22:14:39.760 回答