Re-entry Lock Reentrantlock
can replace synchronized, but synchronized is more flexible.
However, you must have to manually release the lock.
try { lock.lockfinally { lock.unlock();}
A re-entry lock means that any thread can acquire the lock again without being blocked after acquiring the lock.
For Reentrantlock, when the lock is released, the lock calls the N-times Lock () method, and the N-times Unlock () method is called when it is released.
- Trylock () method, Trylock (long timeout, Timeunit unit) method
Try to lock,
This method has a return value, the lock returns True, otherwise false is returned.
If it cannot be locked or cannot be locked for a certain amount of time, the thread can decide whether to wait.
- Lockinterruptibly () method
The thread is blocked when the request is locked, and if it is interrupt, the thread is woken up and asked to process the interruptedexception.
Get the synchronization state logic again:
Determines whether the fetch operation succeeds by determining whether the current thread is the thread that acquires the lock, and if it is the thread that acquires the lock, increments the synchronization state and returns True, indicating that the synchronization state was successful.
In the case of a fair lock, you also need to determine whether the current node in the synchronization queue has a precursor node, and if so, wait for the predecessor thread to acquire the lock and release it before continuing to acquire the lock.
Fair lock and non-fair lock
Fairness is for acquiring locks, fair refers to the order of acquiring locks in the order of request time, that is, FIFO.
The Reentrantlock default is a non-fair lock, which is a fair lock when the object is constructed by invoking a constructor method and entering true.
Read/write Lock Reentrantreadwritelock
Read-write locks allow multiple read threads to be accessed at the same time, but all read and write threads are blocked when the write thread accesses.
Read-write locks maintain a reading lock, a write lock. Also, following the acquisition of a write lock and then acquiring a read lock, and then releasing the order of the write lock, the write lock can be read lock (i.e. lock downgrade )
Reentrantreadwritelock also supports re-entry and fairness Options
Reentrantreadwritelock implements the Readwritelock interface, which only defines methods for acquiring read and write locks, namely Readlock () and Writelock () two methods. Reentrantreadwritelock also provides the following methods:
| Method name | Description |
| :-------- | :-------- |
| int Getreadlockcount () | Returns the number of times the current read lock was fetched. This number of times is not equal to the number of threads acquiring read locks, and a line examples acquires read locks multiple times |
| int Getreadholdcount () | Returns the number of times the current thread acquires a read lock and saves it using Threadlocal |
| Boolean iswritelocked () | Determine if a write lock is obtained |
| int Getwriteholdcount () | Returns the number of times the current write lock has been fetched |
Reentrantreadwritelock maintains the acquisition state of Read and write locks by dividing the synchronization state of the Aqs into high 16-bit (read) and low 16-bit (write)
The status in the diagram indicates that the current thread has acquired a write lock and has been re-entered two times, while acquiring two read locks.
A read-write lock is a bit operation to determine the read-write status.
Set the current synchronization state to S, then:
Write Status S & 0x0000FFFF, that is, the high 16 bits (read) erase
Read status S >>> 16, i.e. right shift 16 bit
Write state increased by 1 o'clock, S + 1
Read status increased by 1 o'clock, S + (1 << 16), i.e. S + 0x00010000
Inference: The synchronization state S is not equal to 0 o'clock, when the write state (S & 0x0000ffff) equals 0 o'clock, the read state (S >>> 16) is greater than 0, that is, the read lock has been acquired.
Acquisition and release of write locks
The write lock supports re-entry , but it is an exclusive lock .
When the current thread acquires a write lock:
- If the current thread has acquired a write lock, the write state is incremented
- If the read lock has been fetched or the thread is not a thread that has already acquired a write lock, the current thread waits
protected Final Boolean Tryacquire(intAcquires) {/** Walkthrough:* 1. If read count nonzero or write count nonzero* and owner is a different thread, fail.* 2. If count would saturate, fail. (This can only* happen if count is already nonzero.)* 3. Otherwise, this thread was eligible for lock if* It is either a reentrant acquire or* Queue policy allows it. If So, update the state* and set owner. */Thread current = thread.CurrentThread();intc =getState();intW =Exclusivecount(c);//Get Write status if(c! =0) {//(note:if c! = 0 and W = = 0 Then shared count! = 0), which is the inference above if(W = =0|| Current! =Getexclusiveownerthread())//Back is re-entry condition return false;if(W +Exclusivecount(acquires) > Max_count)Throw NewError ("Maximum lock count Exceeded"); }if(W = =0&&Writershouldblock(current)) || !compareandsetstate(c, C + acquires))return false;Setexclusiveownerthread(current);return true;}
If there is a read lock, the write lock cannot be obtained because:
Read-write locks to ensure that the operation of a write lock is visible to a read lock, the running read thread cannot perceive the operation of the write thread if the read lock is allowed to acquire the write lock in case it has been acquired.
The release of the write lock is that each time the write state is reduced and the write state is 0, the write lock is released.
Acquisition and release of Read locks
Read locks are shared locks that support re-entry .
Read locks can be obtained simultaneously by multiple threads, and in the absence of write thread access, the read lock can always be successfully fetched (read State plus increase).
Condition interface
Before Java5, implementations of the wait/Notify mode can be implemented with the Wait ()/notify ()/notifyall () and synchronized mates.
Any Java object has the above method, called the Monitor method
The condition interface also provides a similar approach:
Method Name |
Description |
Await () |
The current thread enters a wait state until it is notified or interrupted |
Awaituninterruptibly () |
The current thread enters a wait state until it is notified |
Awaitnanos (Long Nanostimeout) |
The current thread enters a wait state until it is notified or interrupted or timed out, and the return value is the time remaining |
Awaitutil (Date deadLine) |
The current thread goes into a wait state until it is notified or interrupted or arrives at a certain time and is not notified at some time to return true |
Signal () |
Wakes up a thread waiting on condition, which must obtain a condition-related lock before returning from the wait method |
Signalall () |
Wake all the threads waiting on condition, the thread that can be returned from the wait method must obtain the lock associated with the condition |
Gets the condition object must pass the lock's Newcondition () method.
new ReentrantLock();Condition con1 = lock.newCondition();Condition con2 = lock.newCondition();
You must acquire the lock before you use it, and then call the condition method, the following is the implementation of a producer/consumer scenario using condition:
Public classmycontainer2<t> {Final Privatelinkedlist<t> lists =NewLinkedlist<> ();Final Private intMAX =Ten;//maximum of 10 elements Private intCount =0;PrivateLock lock =NewReentrantlock ();PrivateCondition producer = lock.newcondition();PrivateCondition consumer = lock.newcondition(); Public void put(T T) {Try{lock.Lock(); while(lists.size() = = MAX) {//Think about why using while instead of using if? Producer.await(); } lists.Add(t); ++count; Consumer.Signalall();//Notify consumer threads to consume}Catch(Interruptedexception e) {e.Printstacktrace(); }finally{lock.Unlock(); } } PublicTGet() {T t =NULL;Try{lock.Lock(); while(lists.size() ==0) {consumer.await(); } t = lists.Removefirst(); Count--; Producer.Signalall();//Notify producers of production}Catch(Interruptedexception e) {e.Printstacktrace(); }finally{lock.Unlock(); }returnT } Public Static void Main(string[] args) {mycontainer2<string> c =NewMycontainer2<> ();//Start consumer thread for(intI=0; i<Ten; i++) {NewThread (()->{ for(intj=0; j<5; J + +) System. out.println(c.Get()); },"C"+ i).Start(); }Try{Timeunit.SECONDS.Sleep(2); }Catch(Interruptedexception e) {e.Printstacktrace(); }//start producer thread for(intI=0; i<2; i++) {NewThread (()->{ for(intj=0; j< -; J + +) c.put(Thread.CurrentThread().GetName() +" "+ j); },"P"+ i).Start(); } }}
Reference: The Art of Java concurrent programming
The lock of Java concurrent programming