The re-entry lock can completely replace the Synchronized keyword. In earlier versions of JDK5.0, the performance of the re-entry lock was much better than synchronized, but starting with JDK6.0. JDK has done a lot of optimizations on synchronized. The performance gap between the two is small ,
Public classReenterlockImplementsRunnable { Public StaticReentrantlock lock =NewReentrantlock (); Public Static inti = 0; /*** When an object implementing interface <code>Runnable</code> was used * To create a thread, start ing the thread causes the object ' s * <code>run</code> method to being called in that separately executing * Thread. * <p> * The general contract of the method <code>run</code> are that it could take any action wha Tsoever. * * @seeThread#run ()*/@Override Public voidrun () { for(intj = 0; J < 10000000; J + +) {lock.lock ();//Locking Try{i++; } finally{lock.unlock ();//Release Lock } } } Public Static voidMain (string[] args)throwsinterruptedexception {reenterlock T1=NewReenterlock ();//Thread InstanceThread Th1 =NewThread (t1); Thread Th2=NewThread (t1); Th1.start (); Th2.start (); Th1.join (); Th2.join (); System.out.println ("I =" +i); }}
Here we use the re-entry lock to protect the critical zone resource I to ensure the security of multithreading for I operations, we can see that, compared with synchronized, the re-entry lock has a display of the operation process, the developer must manually specify when to lock, when to release the lock, and because of this, The re-entry lock is much better than synchronized for logical control, but it is necessary to release the lock, otherwise the other threads will not have the opportunity to now approach the critical zone resource! Additionally, the re-entry lock allows a thread to acquire the same lock several times in succession, but also releases the same number of times when the lock is released.
- Interrupt response compared to synchronized, if a thread is waiting for a lock, then the result is only two cases, 1 gets the lock execution, 2 he stays in the waiting state, and the use of the re-entry lock, provides another possibility that the thread can be interrupted, that is, during the waiting process, The program can cancel requests for locks as needed.
The following code creates a deadlock, but thanks to the lock interruption, we can easily resolve the deadlock.
Public classIntlockImplementsRunnable { Public StaticReentrantlock Lock1 =NewReentrantlock (); Public StaticReentrantlock Lock2 =NewReentrantlock (); intlock; PublicIntlock (intLock) { This. Lock =lock; } /*** When an object implementing interface <code>Runnable</code> was used * To create a thread, start ing the thread causes the object ' s * <code>run</code> method to being called in that separately executing * Thread. * <p> * The general contract of the method <code>run</code> are that it could take any action wha Tsoever. * * @seeThread#run ()*/@Override Public voidrun () {Try { if(Lock = = 1) {lock1.lockinterruptibly ();//Lock 1 This is a lock request action that you want to make to the interrupt! Try{Thread.Sleep (500); } Catch(interruptedexception e) {e.printstacktrace (); } lock2.lockinterruptibly ();//Lock 2 plus lock}Else{lock2.lockinterruptibly (); Try{Thread.Sleep (500); } Catch(interruptedexception e) {e.printstacktrace (); } lock1.lockinterruptibly ();//Lock 1 plus lock } } Catch(interruptedexception e) {e.printstacktrace (); } finally { if(Lock1.isheldbycurrentthread ()) {//determine if the thread holding its own lock is the current threadLock1.unlock (); } if(Lock2.isheldbycurrentthread ()) {lock2.unlock (); } System.out.println (Thread.CurrentThread (). GetId ()+ ": Thread Exit"); } } Public Static voidMain (string[] args)throwsinterruptedexception {intlock R1=NewIntlock (1);//Thread Instance 1Intlock r2 =NewIntlock (2);//Thread Instance 2Thread T1 =NewThread (R1);//Thread 1Thread t2 =NewThread (R2);//Thread 2T1.start (); T2.start (); Thread.Sleep (1000);//main thread hibernation 1st2.interrupt ();//break one of the threads }}
After thread T1 and T2 start up, T1 takes up rock1 in occupy Rock2 T2 first takes up rock2 then requests rock1 so it is easy to form each other waiting, when we let T2 break, he abandons the application lock1 and then releases Lock2 which is actually T1 thread to complete the task of normal exit, and T2 is interrupted,
- Lock application Wait time in addition to waiting for notification, to avoid deadlocks there is another way, that is, the limit of waiting, that is, to specify a period, beyond the time not to get the lock on the exit
Public classTimelockImplementsRunnable { Public StaticReentrantlock lock =NewReentrantlock (); /*** When an object implementing interface <code>Runnable</code> was used * To create a thread, start ing the thread causes the object ' s * <code>run</code> method to being called in that separately executing * Thread. * <p> * The general contract of the method <code>run</code> are that it could take any action wha Tsoever. * * @seeThread#run ()*/@Override Public voidrun () {Try { if(Lock.trylock (5, Timeunit.seconds)) {//try to get the lock, wait 5 seconds if it times out then falseThread.Sleep (6000); } Else{System.out.println ("Get Lock Failed"); } } Catch(interruptedexception e) {e.printstacktrace (); } finally { if(Lock.isheldbycurrentthread ()) {lock.unlock (); } } } Public Static voidMain (string[] args) {timelock R1=NewTimelock (); Thread T1=NewThread (R1); Thread T2=NewThread (R1); T1.start (); T2.start (); }}
In this case, because the thread that occupies the lock holds the lock for up to 6s, the other thread cannot get the lock in the 5s wait time, so the request lock fails! The Reentrantlock.trylock () method can run without parameters, in which case the current thread attempts to acquire the lock, and if the lock is not occupied by another thread, the request succeeds! And immediately returns true if the lock is occupied by another thread, the schedule you eat first will not do any waiting, Instead, it returns false immediately.
Public classTrylockImplementsRunnable { Public StaticReentrantlock Lock1 =NewReentrantlock (); Public StaticReentrantlock Lock2 =NewReentrantlock (); intlock; PublicTrylock (intLock) { This. Lock =lock; } /*** When an object implementing interface <code>Runnable</code> was used * To create a thread, start ing the thread causes the object ' s * <code>run</code> method to being called in that separately executing * Thread. * <p> * The general contract of the method <code>run</code> are that it could take any action wha Tsoever. * * @seeThread#run ()*/@Override Public voidrun () {if(Lock = = 1) { while(true) { if(Lock1.trylock ()) {Try { Try{Thread.Sleep (500); } Catch(interruptedexception e) {e.printstacktrace (); } if(Lock2.trylock ()) {Try{System.out.println (Thread.CurrentThread (). GetId ()+ ": My Job Done"); return; } finally{lock2.unlock (); } } } finally{lock1.unlock (); } } } } Else { while(true) { if(Lock2.trylock ()) {Try { Try{Thread.Sleep (500); } Catch(interruptedexception e) {e.printstacktrace (); } if(Lock1.trylock ()) {Try{System.out.println (Thread.CurrentThread (). GetId ()+ ": My Job Done"); return; } finally{lock1.unlock (); } } } finally{lock2.unlock (); } } } } } Public Static voidMain (string[] args) {trylock R1=NewTrylock (1); Trylock R2=NewTrylock (2); Thread T1=NewThread (R1); Thread T2=NewThread (R2); T1.start (); T2.start (); }}
In the code above. The lock sequence is very easy to deadlock, and in general, this causes T1 and T2 to wait with each other. But after using Trylock (), it will be greatly improved, the thread will not be silly waiting, but not keep trying. So long as the time is long enough, the thread will always get all the resources it needs.
- Fair lock in most cases. The application of the lock is unfair. Two threads apply for lock A at the same time, who gets the lock a first? This is not necessarily the case, the system will simply pick a random one from the waiting queue of the lock. And the fair lock, that is not the case, he will be in accordance with the order of time, to ensure that A key feature of the fair lock is that there is no hunger, as long as you queue up, eventually you can get the resources, if we use the Synchronized keyword for lock control, then the resulting lock is unfair, and re-enter the lock in sequence we set the fairness of it, the following is his constructor
Public Reentrantlock (Boolean fair) {
Sync = Fair? New Fairsync (): New Nonfairsync ();
When the parameter fair is true, the lock is fair, the fair lock must require the system to maintain an orderly queue, so the implementation cost is higher, the performance is relatively low, so the default lock is unfair.
Synchronized function Expansion: Re-entry Lock (reading notes)