The most common way:
int a =;
Note: In general, this will be set to a class variable, such as the Zhi in Segement and the global lock in copyonwritearraylist
final reentrantlock lock = new Reentrantlock () ;
Lock.lock ()//Get lock
try {
a++;//business logic
} catch (Exception e) {
}finally{
lock.unlock ();/release Lock
}
1, for Reentrantlock need to master the following Reentrantlock creation (Fair lock/non-fair lock) Lock: Lock () Unlock: Unlock ()
First of all, class structure: Reentrantlock-->lock nonfairsync/fairsync-->sync-->abstractqueuedsynchronizer--> Abstractownablesynchronizer Nonfairsync/fairsync-->sync is the three internal class of Reentrantlock node is an internal class of Abstractqueuedsynchronizer
Note: Above these four lines, corresponding relation: "Subclass"--> "Parent class"
2, the creation of Reentrantlock support Fair Lock (Advanced thread first execution) to support the unfair lock (the incoming thread may also be executed first)
Non-fair lock and unfair lock creation non-fair Lock: Reentrantlock () or Reentrantlock (false)
Final Reentrantlock lock = new Reentrantlock ();
Fair Lock: Reentrantlock (True)
Final Reentrantlock lock = new Reentrantlock (TRUE)
Unjust locks are used by default.
The source code is as follows:
Reentrantlock:
/** Synchronizer: A reference to internal class sync * *
private final sync sync;
/**
* Create a non-fair
lock
/Public Reentrantlock () {
sync = new Nonfairsync ();
}
/**
* Create a lock
* @param Fair true--> Fair Lock false--> non-fair
lock
/Public Reentrantlock (Boolean fair {
sync = (FAIR)? New Fairsync (): New Nonfairsync ();
}
There are three internal class Sync/nonfairsync/fairsync in the above source code, where only the definition of the class is listed, and the specific methods in these three classes are introduced at the first subsequent reference.
Sync/nonfairsync/fairsync class Definition:
/**
* A base class for the lock synchronization control. There are two subcategories below: inequitable mechanisms and fair mechanisms. The/
static abstract class Sync with the Abstractqueuedsynchronizer class Extends Abstractqueuedsynchronizer
/**
* Non-fair lock synchronizer * *
Final static class Nonfairsync extends Sync
/ * *
* Fair lock synchronizer
/
final static class Fairsync extends Sync
3. Lock () of a non-fair lock ()
The specific use method:
Lock.lock ();
The following is a simplified version of this overall step, followed by a detailed source code and a detailed version of the steps in the Lock () method section of the source code.
simplified version of the steps: (The core of the non-fair lock)
Attempt to set state (number of locks) from 0 to 1 based on CAs
A, if the setting succeeds, set the thread that the current thread is an exclusive lock;
B, if the setting fails, the number of locks will be acquired again.
B1, if the lock number is 0, and then set the state (lock quantity) from 0 to 11 based on the CAS attempt, and if the setting succeeds, set the thread that the current thread is an exclusive lock;
B2, if the lock number is not 0 or the top attempt fails again, see if the current thread is already an exclusive lock thread, and if so, the current number of locks is +1; if not, the thread is encapsulated in a node and added to the wait queue. Waits to be awakened by its previous thread node.
Source code: (before introducing the source code, there is an overall impression of the steps to get the lock, which is the "simplified version of the steps" above)
3.1, Reentrantlock:lock ()
/**
* Get a lock
* Three case:
* 1, if the current lock is not held by any thread (including the current thread), acquire the lock immediately, lock the number of ==1, then execute the corresponding business logic
* 2, if the present thread is holding the lock, Then the lock number +1, then the corresponding business logic
* 3, if the next lock is held by another thread, the current thread is dormant until the lock is acquired, the current thread is awakened, the number of locks is ==1, then the corresponding business logic/public
void is executed.
Lock () {
sync.lock (),//The Lock () method that calls the Nonfairsync (not fair lock) or Fairsync (Fair lock)
}
3.2, Nonfairsync:lock ()
/** * 1 First set the state (lock quantity) from 0 to 1 based on the CAs, if the setting succeeds, set the thread that the current thread is an exclusive lock;--> the request successfully--> the first jump in line * 2) If the setting fails (that is, the current number of locks may
It's already 1, that is, in the process of trying, has been the other line enters upgradeable a step to occupy the lock), this time the current thread execution acquire (1) method * 2.1) Acquire (1) method first calls the bottom of the Tryacquire (1) method, in this method, first get the lock number state, * 2.1.1) if 0 (proof that the exclusive lock has been freed, no threads are currently in use), we continue to use CAs to set the state (number of locks) from 0 to 1, if the setting succeeds, the current thread exclusive lock;--> request Success--> the second queue; of course,
If the setting is unsuccessful, return false * 2.2.2 Directly if it is not 0, to determine if the current thread is the currently exclusive lock thread, and if so, the current lock number state value +1 (which is the source of the name of the reentrant Lock)--> Request Success *
* Bottom of the process: After the request fails, the current thread chain is queued and suspended, and waits to be awakened.
* * 2.2.3) If the last execution in the Tryacquire (1) method is unsuccessful, that is, the request failed, return false, and proceed to the acquirequeued (Addwaiter (node.exclusive), arg) method * 2.2 In the above method, first use Addwaiter (node.exclusive) to encapsulate the current thread into the node node, and then add the node to the wait queue (first quickly, if the team is unsuccessful, It uses the normal queue method infinite loop until the node node is joined to the queue. * 2.2.1) Quick team: If the synchronization wait queues exist tail nodes, the CAS attempt is used to set the tail node to node and the previous tail node is inserted before node * 2.2.2) Normal Team: If the synchronization wait queue does not have a tail node or if the above CAs attempt does not succeed, perform a normal team (the method is an infinite loop, that is, until the team is joined)--> first block * 2.2.2.1) if the tail node is empty (initialize the synchronization wait queue), create a dummy section Pointand set the node up to the end node through the CAS attempt, if the setting succeeds, the tail node also points to the dummy node (that is, both the head and tail nodes point to the dummy node) * 2.2.2.1) if the tail node is not empty, perform the same logic as the quick queue, that is, use the CAS attempt to set the tail node to node, and before inserting the previous tail node into node * Finally, if the team is successful, return to the team nodes node, if not smooth, infinite loop to execute 2.2 below the process, until the team * 2.3) node nodes after the team, to execute a Cquirequeued (final node node, int arg) (This is the process of an infinite loop, where it should be noted that an infinite loop is equal to blocking, that multiple threads can loop indefinitely--each thread can perform its own loop, In order to make the node in the queue at the end of the line forward) * 2.3.1) gets the node's predecessor p, if p is the head node, continue to use the Tryacquire (1) method to try to request a successful,--> the third time queue (of course, this queue does not necessarily give it the right to execute, ), * 2.3.1.1) if the first request succeeds without interrupting its own thread, if the thread is suspended after the loop and the request succeeds, use Selfinterrupt () to interrupt itself * (Note p==head&&t Ryacquire (1) Success is the only way to jump out of the loop, this will be blocked until the other thread is in the process of executing, continuously reducing the front node of p until p becomes head and node request succeeds-that is, node is awakened before exiting the loop) * 2.3.1 .2) If P is not a head node, or if Tryacquire (1) request is unsuccessful, execute Shouldparkafterfailedacquire (node pred, node node) to detect if the current node is safe to be suspended, * 2.3. 1.2.1) If the pred wait state of node's predecessor is signal (that is, the thread that wakes up the next node), the node's thread can be safely suspended, executing 2.3.1.3) * 2.3.1.2.2) if node's predecessor Pred wait state is CA Ncelled, then the pred thread is canceled, and we will remove several successive canceled predecessors from the queue before pred.Returns False (that is, cannot be suspended), and then continues to execute 2.3 in the above code * 2.3.1.2.3) if node's pred wait state is in addition to the other two states, use CAs to attempt to set the wait state of the precursor node to signal and return false (because CAs may fail, regardless of whether it fails, it returns false, after the next execution of the method, the Pred wait status is signal), and then proceed to execute the above code * 2.3.1.3 in 2.3) if it can be safely suspended, execute PARKANDCHEC
Kinterrupt () suspends the current thread, then executes the previous code in 2.3) * Finally, until all nodes of the node's precursor p are executed, our p becomes the head node, and Tryacquire (1) Requests success, jumps out of the loop, and executes.
* (in the entire process before P becomes the head node, we find that the process is not interrupted) * 2.3.2) of course in 2.3.1), we will perform cancelacquire (node node) to cancel node acquisition lock intent. */FINAL void lock () {if (compareandsetstate (0, 1))//If the CAS attempt succeeds Setexclusiveow
Nerthread (Thread.CurrentThread ());//Set thread else acquire (1) for which the current thread is an exclusive lock; }
Note: In this method, I list the detailed process for a thread to acquire a lock and look at the annotation myself.
The following is a list of several methods and related properties that are called in Nonfairsync:lock ().
3.2.1, Abstractqueuedsynchronizer: Lock Quantity state Property + related method:
/**
* Lock Number * *
private volatile int state;
/**
* Acquire lock number * *
protected final int getState () {return state
;
}
Protected final void SetState (int newstate) {state
= newstate;
}
Note: State is a volatile type.
3.2.2, Abstractownablesynchronizer: Attribute +setexclusiveownerthread (Thread t)
/**
* currently has exclusive lock thread *
*
private transient thread exclusiveownerthread;
/**
* Set exclusive lock thread for thread T
/protected final void Setexclusiveownerthread (thread t) {
EXCLUSIVEOWNERTHR