We all know that in Java, when multiple threads require concurrent access to shared resources, synchronization is required, and the synchronization method we often use is the synchronized keyword, in fact, before jdk1.5, there is only one synchronized. In jdk1.5, a new synchronization mode-display lock is provided. The display lock is released with the Java.util.concurrent package, and the Java.util.concurrent package is a concurrency toolkit written by the concurrent great God Doug Lea, with many other useful concurrency tools in addition to the display lock.
What is a display lock
What is a display lock? Use a section of code to illustrate:
PackageCom.gome;ImportJava.util.concurrent.locks.Lock;ImportJava.util.concurrent.locks.ReentrantLock; Public classLockpractice {Private Static intA=0; Private StaticLock lock=NewReentrantlock (); Public Static voidincreatebysynchronized () {a=0; for(inti = 0; i < 1000; i++) {Thread T=NewThread (NewRunnable () { Public voidrun () { for(intj = 0; J < 100; J + +) { synchronized(Lockpractice.class) {a++; } } } }); T.start (); } while(Thread.activecount () >1) {Thread.yield (); } System.out.println (a); } Public Static voidIncreatebylock () {a=0; for(inti = 0; i < 1000; i++) {Thread T=NewThread (NewRunnable () { Public voidrun () { for(intj = 0; J < 100; J + +) {lock.lock (); Try{a++; } finally{lock.unlock (); } } } }); T.start (); } while(Thread.activecount () >1) {Thread.yield (); } System.out.println (a); } Public Static voidMain (string[] args) {increatebysynchronized (); Increatebylock (); }}
Execution Result:
Explain:
There are two methods in class Lockpractice increatebysynchronized () and Increatebylock (), both of which successfully add a to 100000 with multi-threaded concurrency without a race condition (race condition Problem
The synchronization of Increatebysynchronized () is implemented by our familiar synchronized keyword:
synchronized (Lockpractice. class ) {A+ +;}
The meaning of this code is that when a thread a enters the synchronized code block, it blocks other threads to enter the code block until a code block is executed. The Synchronized keyword associates a lock object, which is lockpractice.class. The Synchronized keyword is implemented by the JVM, and when a thread enters the synchronized block, it records the thread information in the object header (Markword) of the associated lock object (which can simply be understood as the threading ID) so that the lock object is exclusive to the current thread. , other threads attempting to acquire this lock object will be blocked.
So the essence of a thread entering and exiting the synchronized code block is that the thread acquires and frees the lock object.
The synchronization Code of Increatebylock () is as follows, where lock is the global variable private static Lock lock=new Reentrantlock ();
Lock.lock (); Try { a++finally { lock.unlock ();}
As you can see from the code, the use of the display lock lock is very much like the nature of the synchronized, it also defines a lock object (new Reentrantlock ()), and then locks before entering the synchronization code, releasing the lock after the synchronization code is executed.
But the bottom of the display lock is completely different from the synchronized, and there is no use of the underlying object (Markword), which shows the same behavior as synchronized (the first thread that accesses the synchronization code gets the lock and blocks the later thread).
Advantages of displaying locks
From the above description, the display lock realizes the same function as synchronized, but it is more complicated to write (need to lock and unlock manually, but also to write finally to prevent the lock from being released after the exception), why join the display lock?
We can see the clues from the method provided by the lock interface:
Method name |
Describe |
void Lock () |
Get lock |
void Lockinterruptibly () throws Interruptedexception |
Can be interrupted to obtain a lock, the process of acquiring a lock in the course of a response to interrupt |
Boolean Trylock () |
Try non-blocking get lock, return immediately after calling method, return true successfully, fail return false |
Boolean Trylock (long time, Timeunit unit) throws Interruptedexception |
Acquires a lock within the timeout period, the arrival time-out will return false, or it can respond to an interrupt |
void unlock (); |
Release lock |
Condition newcondition (); |
Gets the wait component, which waits for the component to implement a function similar to the object.wait () method |
As can be seen from the interface provided by lock, the display lock has at least the following features than synchronized:
- Interruptible acquisition Lock: When a lock is acquired using the Synchronized keyword, if the thread is not acquired to be blocked, then the thread is not responding to interrupts (interrupt) and is interrupted when acquiring the lock using lock.lockinterruptibly (). The thread throws an interrupt exception.
- Non-blocking acquisition lock: When a lock is acquired using the Sync keyword, if it is not successfully fetched, only if it is blocked, and if the lock is acquired using Lock.trylock (), it will not block but return FALSE if it is not successful.
- You can limit the timeout for acquiring locks: use Lock.trylock (long time, Timeunit unit).
- In fact, there are other advantages of the display lock, such as the same lock object can have multiple waiting queue (equivalent to object.wait ()), we will talk about later.
In fact, in addition to more features, the display lock has a big advantage: Synchronized synchronization is implemented at the bottom of the JVM, for the general programmer, when the program encountered unexpected behavior, in addition to checking official documents there is little other way While the display lock in addition to the individual operation with the underlying unsafe class, almost all are implemented in the Java language, we can learn to display the source of the lock, to more handy to use the display lock.
Disadvantages of displaying locks
Of course, the display lock is not perfect, otherwise Java will not retain the Synchronized keyword, the main drawback of the display lock is two:
- The use of the complex, mentioned earlier, need to be manually locked, unlocked, but also must be able to unlock in the abnormal state. And the use of synchronized is much simpler.
- Inefficient, the Synchronized keyword is implemented at the bottom of the JVM, so many optimizations are used to optimize speed (favor lock, light lock, etc.), while the display lock is less efficient.
Therefore, when synchronization is required, priority is given to using the Synchronized keyword, and only the display lock is considered when the Synchronized keyword does not meet the requirements.
Summarize
This article describes what a display lock is, the advantages and disadvantages of displaying a lock, and, under what circumstances, a display lock.
The following article focuses on the underlying implementation of the display lock: the implementation of the queue Synchronizer (Abstractqueuedsynchronizer), the implementation of the re-entry lock (Reentrantlock), the implementation of the read-write lock (Readwritelock), the Wait/notification ( Condition) is implemented.
A summary of Java explicit lock learning: An Introduction