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

Jam*_*sen 15 java locking synchronized reentrancy

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

我的猜测是"不",但我希望是错的.

例:

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

ReentrantLock lock = new ReentrantLock();
Run Code Online (Sandbox Code Playgroud)

线程1运行:

synchronized (lock) {
    // blah
}
Run Code Online (Sandbox Code Playgroud)

线程2运行:

lock.lock();
try {
    // blah
}
finally {
    lock.unlock();
}
Run Code Online (Sandbox Code Playgroud)

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

eri*_*son 15

不,线程2 lock()甚至可以在线程1 synchronized相同时使用lock.这就是文档所说的内容:

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


Nei*_*fey 9

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

  • 同步机制使用"内置于"JVM中的锁定机制; 底层机制受特定JVM实现的约束,但通常使用原始比较和设置操作(CAS)指令的组合,用于不争用锁的情况加上OS提供的底层锁定机制;
  • 诸如ReentrantLock之类的锁类基本上是用纯Java编写的(通过Java 5中引入的库,它将CAS指令和线程去调度暴露给Java),因此在OS中更加标准化并且更可控(见下文).

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

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

功能明智的:

  • 同步机制提供最少的功能(你可以锁定和解锁,锁定是一个全有或全无的操作,你更多地受制于OS编写者决定的算法),尽管具有内置语法和一些监控的优势内置于JVM中;
  • 显式锁类提供更多控制,特别是你可以指定一个"公平"锁定,锁定超时,如果你需要改变锁定的behiour覆盖......