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

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

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

例:

想象一下,线程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在同一个lock synchronized ,线程2也可以lock() 。 这就是文档所说的内容:

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

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

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

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

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

function明智的:

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

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

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