Reentrantlock is a reentrant lock that can support a thread to repeatedly lock resources, and he also supports fair locking and unequal locking. The Synchronized keyword also implicitly supports re-enter, such as a recursive method of synchronized modification, when the method executes, The execution thread can still obtain the lock multiple times after acquiring the lock Reentrantlock although it did not support implicit entry like the Synchronized keyword, when the lock () method was invoked, the thread that had acquired the lock was able to invoke lock () again. Method gets the lock without being blocked. Fair Lock definition
Fair Lock is the absolute time on the lock to obtain the first request must be satisfied, the fair access to the lock is the longest waiting time of the thread to obtain the first lock, can also be said to acquire the lock in sequence. Reentrantlock provides a constructor that controls whether a fair lock is possible.
Advantages and Disadvantages
There is no unfair lock efficiency, but can reduce the probability of starvation, the longer the waiting thread is easier to acquire the lock. Implement Re-enter
Re-entry means that any thread can acquire the lock again without being blocked by the lock after acquiring the lock
The thread acquires the lock again: the lock needs to identify whether the thread acquiring the lock is the thread that currently occupies the lock, and if so, succeeds again.
Final release of the Lock: the thread repeats the lock for n times, and then the lock is freed by another thread after it is released in the nth time. The final release of the lock requires that the lock be counted for the gain, the count indicates the number of times the current lock has been repeatedly fetched, and when the lock is released, the count is reduced, and when the count equals 0, the lock has been released successfully.
Let's take a look at the code instances where the synchronization status is not fairly obtained:
/** * performs Non-fair.
Tryacquire is * implemented into subclasses, but both need Nonfair * try for Trylock method.
* Final Boolean nonfairtryacquire (int acquires) {final Thread current = Thread.CurrentThread ();
int c = GetState (); If there is no concurrent thread accessing if (c = = 0) {//If the sync status is updated successfully, the lock succeeds if (compareandsetstate 0, Acqui
Res)) {Setexclusiveownerthread (current);
return true; }//If a Chengga lock has been wired, determine if the locked thread is the current thread and if it is again locked successfully else if (s = = Getexclusiveownerthread (
) {int NEXTC = c + acquires;
if (NEXTC < 0)//overflow throw new Error ("Maximum lock count Exceeded");
SetState (NEXTC);
return true;
return false; }
The thread that successfully acquired the lock acquires the lock again, but only adds the sync state value, which requires reentrantlock to reduce the synchronization state while releasing the sync state, releasing the lock code as follows
Protected Final Boolean tryrelease (int releases) {
int c = getState ()-releases;
If the current request thread is not the last lock-locked thread that throws an exception if
(Thread.CurrentThread ()!= getexclusiveownerthread ())
throw new Illegalmonitorstateexception ();
Boolean free = false;
If the sync status is 0, the lock completely frees if
(c = = 0) {Free
= true;
Setexclusiveownerthread (null);
}
Reduce the synchronization status, reduced to 0 release lock
setstate (c);
return free;
}
If the lock is fetched n times, then the pre (n-1) tryrelease (int releases) method must return False, and only the synchronization state is completely freed to return true. As you can see, this method sets the synchronization state to 0 as the final release condition, and when the synchronization state is 0 o'clock, the owning thread is set to null and returns True, indicating that the release succeeded. the difference between fair and unequal locks
If a lock is fair, then the order of acquisition of the lock should conform to the absolute time order of the request, i.e. FIFO
For unfair locks as long as the CAS set synchronization state successfully indicates that the current thread acquired the lock, the fair lock is certainly different, you have to consider those waiting for longer threads, let us look at the Fair lock Source:
Protected Final Boolean tryacquire (int acquires) {
final Thread current = Thread.CurrentThread ();
int c = getState ();
if (c = = 0) {
///Not only to synchronize the status update success, but also to determine whether the current node in the synchronization queue has a predecessor node, if there is a description of the thread earlier request lock, so you need to wait for the precursor node to acquire and
/or release the lock before you can continue
Hasqueuedpredecessors () &&
compareandsetstate (0, acquires)) {
setexclusiveownerthread (current);
return true;
}
else if (current = = Getexclusiveownerthread ()) {
int nextc = c + acquires;
if (NEXTC < 0)
throw new Error ("Maximum lock count Exceeded");
SetState (NEXTC);
return true;
}
return false;
}
}
Here we write a code instance that distinguishes between fair and unfair locks
public class Fairandunfairtest {/** * public Reentrantlock (Boolean fair) {sync = fair? New Fairsync ()
: New Nonfairsync ();
} * * private static Lock Fairlock = new Reentrantlocktest (true);
private static Lock Unfairlock = new Reentrantlocktest (false);
public static void Main (string[] args) {testlock (unfairlock);//Testlock (Fairlock); public static void Testlock (lock Lock) {for (int i=0;i<10;i++) {new Thread (new Job (lock), i+
"). Start ();
} private static class Job extends thread{private lock lock;
The public Job (lock lock) {This.lock = lock;
public void Run () {lock.lock (); try {//continuously prints Thread System.out.println ("Lock by [" + Thread.CurrentThread ()) in the current tread and queues multiple times
. GetName () + "'],and Waiting" + ((reentrantlocktest) lock). Getqueuedtheads ()); finally {LocK.unlock ();
@SuppressWarnings ("serial") private static class Reentrantlocktest extends reentrantlock{
Public Reentrantlocktest (Boolean fair) {Super (FAIR); Public collection<thread> getqueuedtheads () {list<thread> List = new Arraylist<thread
> (Super.getqueuedthreads ());
Flip Set Order Collections.reverse (list);
return list; }
}
}
The result of the unfair lock run is as follows, the thread does not get the lock, not in the order
Lock by [' 0 '],and waiting [Thread[1,5,main], Thread[2,5,main]]
lock by [' 7 '],and waiting [Thread[1,5,main], thread[2 , 5,main], Thread[3,5,main], Thread[4,5,main], Thread[5,5,main], Thread[6,5,main]
"Lock by [' 1 '],and waiting [ Thread[2,5,main], Thread[3,5,main], Thread[4,5,main], Thread[5,5,main], Thread[6,5,main, Thread[8,5,main], Thread[ 9,5,main]]
Lock by [' 2 '],and waiting [Thread[3,5,main], Thread[4,5,main], Thread[5,5,main], Thread[6,5,main], Thread[8,5,main], Thread[9,5,main]]
Lock by [' 3 '],and waiting [Thread[4,5,main], Thread[5,5,main], thread[6,5, Main], Thread[8,5,main], Thread[9,5,main]]
Lock by [' 4 '],and waiting [Thread[5,5,main], Thread[6,5,main], thread[ 8,5,main], Thread[9,5,main]]
Lock by [' 5 '],and waiting [Thread[6,5,main], Thread[8,5,main], Thread[9,5,main]]
Lock by [' 6 '],and waiting [Thread[8,5,main], Thread[9,5,main]]
Lock by [' 8 '],and waiting [Thread[9,5,main]]
Lock by [' 9 '],and waiting []
The results of the fair lock are as follows: The thread acquires the lock in order
Lock by [' 0 '],and waiting [Thread[1,5,main], Thread[2,5,main]]
lock by [' 1 '],and waiting [Thread[2,5,main], thread[3 , 5,main], Thread[4,5,main], Thread[5,5,main], Thread[6,5,main], Thread[7,5,main]
"Lock by [' 2 '],and waiting [ Thread[3,5,main], Thread[4,5,main], Thread[5,5,main], Thread[6,5,main], Thread[7,5,main, Thread[8,5,main], Thread[ 9,5,main]]
Lock by [' 3 '],and waiting [Thread[4,5,main], Thread[5,5,main], Thread[6,5,main], Thread[7,5,main], Thread[8,5,main], Thread[9,5,main]]
Lock by [' 4 '],and waiting [Thread[5,5,main], Thread[6,5,main], thread[7,5, Main], Thread[8,5,main], Thread[9,5,main]]
Lock by [' 5 '],and waiting [Thread[6,5,main], Thread[7,5,main], thread[ 8,5,main], Thread[9,5,main]]
Lock by [' 6 '],and waiting [Thread[7,5,main], Thread[8,5,main], Thread[9,5,main]]
Lock by [' 7 '],and waiting [Thread[8,5,main], Thread[9,5,main]]
Lock by [' 8 '],and waiting [Thread[9,5,main]]
Lock by [' 9 '],and waiting []
The
Fair locks are run several times occasionally with individual threads that do not follow the sequence, sometimes the following results appear, there are reasons to be able to leave a message, thank you
lock by [' 1 '],and waiting [Thread[0,5,main], Thread[2,5,main]] Lock by [' 0 '],and waiting [ Thread[2,5,main], Thread[3,5,main], Thread[5,5,main], Thread[4,5,main], Thread[7,5,main, Thread[6,5,main], Thread[ 9,5,main], Thread[8,5,main]] Lock by [' 2 '],and waiting [Thread[3,5,main], Thread[5,5,main], Thread[4,5,main], Thread[ 7,5,main], Thread[6,5,main], Thread[9,5,main], Thread[8,5,main]] Lock by [' 3 '],and waiting [Thread[5,5,main], Thread[ 4,5,main], Thread[7,5,main], Thread[6,5,main], Thread[9,5,main], Thread[8,5,main]] Lock by [' 5 '],and waiting [Thread[ 4,5,main], Thread[7,5,main], Thread[6,5,main], Thread[9,5,main], Thread[8,5,main]] Lock by [' 4 '],and waiting [Thread[ 7,5,main], Thread[6,5,main], Thread[9,5,main], Thread[8,5,main]] Lock by [' 7 '],and waiting [Thread[6,5,main], Thread[ 9,5,main], Thread[8,5,main]] lock by [' 6 '],and waiting [Thread[9,5,main], Thread[8,5,main]] lock by [' 9 '],and waiting [Thr Ead[8,5,main]] Lock by [' 8 '],and waiting []
Theoretically unfair locks will appear with the same thread for continuous acquisition of locks, I do not have a simulation here, if there is a good way to leave a message, thank you
Fair locks Guarantee the acquisition of locks in accordance with the FIFO principle, at the cost of a large number of thread switching. While unfair locks may cause threads to "starve", very few thread switches guarantee their greater throughput