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

2022-09-03 06:01:39

在 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()


答案 1

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

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


答案 2

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

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

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

(我还应该说,在最新版本的 Hotspot 中,同步的性能得到了改进;在最新版本上可能没有太多功能,甚至在其他情况下也是如此 - 这显然是一个环境中的一个测试。

功能方面:

  • 同步机制提供了最小的功能(您可以锁定和解锁,锁定是全有或全无的操作,您更受操作系统编写者决定的算法的影响),尽管具有内置语法和JVM内置的一些监视的优势;
  • 显式锁类提供了更多的控制,特别是您可以指定“公平”锁,超时锁定,如果需要更改锁的behiour,则覆盖...

推荐