Mixing synchronized() with ReentrantLock.lock()

十年热恋 提交于 2019-12-20 11:59:05

问题


In Java, do ReentrantLock.lock() and ReetrantLock.unlock() use the same locking mechanism as synchronized()?

My guess is "No," but I'm hoping to be wrong.

Example:

Imagine that Thread 1 and Thread 2 both have access to:

ReentrantLock lock = new ReentrantLock();

Thread 1 runs:

synchronized (lock) {
    // blah
}

Thread 2 runs:

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

Assume Thread 1 reaches its part first, then Thread 2 before Thread 1 is finished: will Thread 2 wait for Thread 1 to leave the synchronized() block, or will it go ahead and run?


回答1:


No, Thread 2 can lock() even when Thread 1 is synchronized on the same lock. This is what the documentation has to say:

Note that Lock instances are just normal objects and can themselves be used as the target in a synchronized statement. Acquiring the monitor lock of a Lock instance has no specified relationship with invoking any of the lock() methods of that instance. It is recommended that to avoid confusion you never use Lock instances in this way, except within their own implementation.




回答2:


The two mechanisms are different. Implementation/performance wise:

  • the synchronized mechanism uses a locking mechanism that is "built into" the JVM; the underlying mechanism is subject to the particular JVM implementation, but typically uses a combination of a raw compare-and-set operation (CAS) instruction for cases where the lock isn't contended plus underlying locking mechanisms provided by the OS;
  • the lock classes such as ReentrantLock are basically coded in pure Java (via a library introduced in Java 5 which exposes CAS instructions and thread descheduling to Java) and so is somewhat more standardised across OS's and more controllable (see below).

Under some circumstances, the explicit locks can perform better. If you look at this comparison of locking mechanisms I performed under Java 5, you'll see that in that particular test (multiple threads accessing an array), explicit lock classes configured in "unfair" mode (the yellow and cyan triangles) allow more throughput than plain synchronized (the purple arrows).

(I should also say that the performance of synchronized has been improved in more recent versions of Hotspot; there may not be much in it on the latest versions or indeed under other circumstances-- this is obviously one test in one environment.)

Functionality-wise:

  • the synchronized mechanism provides minimal functionality (you can lock and unlock, locking is an all-or-nothing operation, you're more subject to the algorithm the OS writers decided on), though with the advantage of built-in syntax and some monitoring built into the JVM;
  • the explicit lock classes provide more control, notably you can specify a "fair" lock, lock with a timeout, override if you need to alter the lock's behiour...



回答3:


Why did you make the balance static in Account class? Remove static and it should work.

Also, have a question about your thread usage. In your TestMain you create new threads and assign runnables like WithdrawRequests & DepositRequests. But again you create new threads inside the constructors of those runnables. This will cause the run method to be executed twice!



来源:https://stackoverflow.com/questions/2901079/mixing-synchronized-with-reentrantlock-lock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!