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?
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.
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...
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