The implementation principle of lock in Java and contract

Source: Internet
Author: User

1. Introduction and use of Lock

Lock is the thread synchronization tool introduced in Java 1.5, which is used primarily for the control of shared resources under multithreading. Essentially lock is just an interface (in Java\util\concurrent\locks in the source bundle), which contains the following methods

 //attempts to acquire a lock, gets succeeded, or blocks the current thread void lock (); //attempts to acquire a lock, the thread is interrupted before the lock is successfully acquired, discards the fetch lock, throws an exception void lockinterruptibly () throws interruptedexception; //tries to acquire the lock, gets the lock succeeds returns TRUE, otherwise returns false boolean trylock (); //attempts to acquire a lock, returns true if the lock is acquired within a specified time, otherwise returns false, throws an exception long time, Timeunit unit)       
                                   Release lock  //Return the current lock condition variable, through the condition variable can implement similar notify and wait function, a lock can have more than one condition variable condition newcondition ();

Lock has three implementation classes, one is Reentrantlock, the other two are two static inner classes Readlock and Writelock in the Reentrantreadwritelock class.

How to use: when accessing (mutually exclusive) a shared resource under multi-threading, the access is locked before access is completed, and the unlocked operation is recommended to be put into the finally block.

try {       finally {l.unlock ();}

Note that the lock is outside of the try block for resource access, especially if you use the Lockinterruptibly method to lock, which is necessary to prevent the thread from being interrupted when it acquires the lock.

try {     l.lockinterruptibly ();  The unlock statement in the finally block is not executed when a lock failure is obtained      try{          //access the resource protected by this lock     }//TODO Auto-generated Catch block E.printstacktrace ();}   

2. The basic idea of implementing the lock interface

there is a need to implement the lock function, two prerequisites, one is a variable representing the (lock) state (we assume that 0 means no thread acquires the lock, 1 means that there are threads holding the lock), the other is a queue, and the node in the queue represents the thread that blocked because the lock could not be acquired. To solve the problem of inconsistent multithreading caches under multicore processors, variables that represent states must be declared as Voaltile types, and atomicity and visibility are guaranteed for certain operations on variables and queues that represent states. The operation of atomicity and visibility is mainly implemented by means of the atomic package.

the approximate process by which a thread acquires a lock (there is no consideration of the case where reentrant and acquire lock processes are interrupted or timed out)

1. Read the variable that represents the lock state

2. If the value of the variable representing the state is 0, then when the thread attempts to set the value of the variable to 1 (through the CAS operation), when multiple threads simultaneously set the value of the variable representing the state from 0 to 1 o'clock, only one thread succeeds, its

Its thread will fail

2.1 If successful, it means that the lock is acquired,

2.1.1 If the thread (or node) is already in the queue, it is dequeue (and the next node becomes the head node of the queue)

2.1.2 If the thread is not into row, the queue is not maintained

The current thread then returns from the lock method and accesses the shared resource.             

2.2 If it fails, the current thread puts itself in a waiting (locked) queue and blocks itself , at which point the thread has been blocked in the lock method, not returned from that method (it is still in the lock method after being awakened ). and proceed from the next statement, and this will return to the 1th step to start again.

3. If the value of the variable that represents the state is 1, put the current thread in the wait queue, then block itself (still in the lock method after wake-up and continue from the next statement, and this will return to the 1th Step to start again)

Note: Wakeup does not mean that the line Cheng Nen is running immediately, but rather that the thread is in a ready state and can only be run

general procedure for thread release locks

1. The thread releasing the lock sets the value of the state variable from 1 to 0 and wakes up the queue's first node in the Wait (lock) line, releasing the lock thread from the Unlock method and continuing to execute the code behind the thread

2. The wake-up thread (the first node in the queue) and the possible and non-queued and ready-to-acquire threads compete to acquire the lock, and the process of acquiring the lock repeatedly

Note: There may be multiple threads competing to acquire the lock at the same time, but only one thread at a time can release the lock, and the node in the queue needs its previous node to wake it up, for example, a queue a<-b-<c, that is, wake-up when the lock is released by a b,b release of the lock C

3. Fair lock and non-fair lock

Locks can be divided into fair and unfair locks, re-entry locks and non-reentrant locks (the introduction of the re-entry lock is described in Reentrantlock source code analysis), the above process is actually an unfair lock acquisition and release process.

The fair lock strictly follows the first served to get the lock, while the non-fair lock allows the lock to be captured in the queue.

The process of fair lock acquisition is somewhat different, in the use of a fair lock, a thread wants to acquire a lock, not only need to determine whether the current state of the variable value is 0, but also to determine whether there are other threads in the queue, if the queue is also wired to indicate that the current thread needs to queue, into row operation, and block itself; To try to get the lock. In the case of an unfair lock, when the value of the variable representing the state is 0, you can try to acquire the lock, regardless of whether the queue is empty, thus realizing the lock-in-queue acquisition. In general, the throughput rate of an unfair lock is higher than that of a fair lock, and we generally use a non-fair lock.

Here it is necessary to explain the circumstances in which the value of the variable that represents the state of the lock is 0 and there are still other threads in the queue waiting to acquire the lock.

Suppose there are three threads a, B, C. A thread is a running thread and holds a lock, and there is a C thread in the queue, at the head of the team. Now that a thread is releasing the lock, the process operation can be divided into two steps:

1. Change the value of the variable representing the lock state from 1 to 0.

2. C thread is awakened, here to clear two points:

(1) C Thread Wake up does not mean that C thread start execution, c thread is now in a ready state, to wait for the operating system scheduling

(2) the C thread is not currently out of order, and the C thread is going into a running state and will not be out of order until the lock is acquired through the competition.

If the C thread is not in the running state at this time, and the B thread in the queue does not acquire the lock, B will find that although there are currently no threads holding the lock, but the queue is not empty (the C thread is still in the queue), to meet the characteristics of the first served (b after c to perform the operation to acquire the lock), The B-thread cannot attempt to acquire the lock, but instead into row the operation.

4. Basic idea of realizing condition interface

The Condition essence is an interface that contains the following methods

void awaituninterruptibly ();
Let the thread enter the wait notification state, time-out to end the wait state, and throw  an exception long Awaitnanos (Boolean await (//)all threads in the condition queue, from waiting for notification blocking state to waiting lock blocking state void Signalall ();   

The inside of a condition instance actually maintains a queue in which the nodes in the queue represent threads that the thread itself calls the await method to block because (some conditions are not met). There are two important methods in the condition interface, namely the await method and the signal method. Before the thread calls this method, the thread must have acquired the lock that the condition instance is attached to. There are two reasons for this, (1) for the await method, it performs a release lock operation internally, so the lock must be acquired before use. (2) for the signal method, it is to avoid the queue-out competition caused by multiple threads calling the Singal method of the same condition instance simultaneously. The following are the execution processes for these two methods.

Await method:

1. into row to the conditional queue (Note that this is not a queue waiting to be locked )

2. Release the lock

3. Blocking the thread itself

------------is awakened after execution-------------

4. Try to get the lock (the thread is no longer in the condition queue when executing here, but it is in the Waiting (locked) queue , see the Signal method)

4.1 Succeeded, returned from the await method, executes the code behind the thread

4.2 Failure, blocking itself (wakes the previous node when it releases the lock)

Note: When the await method is called by its own thread, the thread is blocked in the await method and is not returned from the await method, and then resumes execution of the code later in the await method (that is, the code that acquires the lock). You can see that the await method frees the lock and tries to get the lock. When the lock is unsuccessful, the current thread still blocks into the await method, waits for the previous node to release the lock, and then wakes it up.

Signal method:

1. Remove the first node of the condition queue and put it in the tail of the queue waiting to be locked

2. Wake the thread corresponding to the node

Note: signal is called by another thread

Use routines for lock and condition

The following example is the use of lock and condition implementation of the B thread first print a message, and then a thread print two sentences (can not be interrupted), alternating 10 times after the end

PublicClass Conditiondemo {Volatileint key = 0; Lock L =New Reentrantlock (); Condition C = l.newcondition ();PublicStaticvoid Main (string[] args) {Conditiondemo demo =New Conditiondemo ();New Thread (demo.New A ()). Start ();New Thread (demo.New B ()). Start (); }Class AImplements runnable{@OverridePublicvoid Run () {int i = 10;while (i > 0) {l.lock ();try{if (key = = 1) {System.out.println ("a is Running"); System.out.println ("a is Running"); i--; key = 0; C.signal ();} else{c.awaituninterruptibly ();}} finally{l.unlock ();}} }} class B implements runnable{@Override public void run () {int i = ten; while (i > 0) {l.lock (); try{if (key = = 0) {System.out.println ("b is Running"); i--; key = 1; C.signal (); }else{c.awaituninterruptibly ();}} finally{l.unlock ();}} } }}

5. The difference between lock and synchronized

1. Lock unlocking and unlocking are implemented by the Java code in conjunction with the native method (invoking the relevant method of the operating system), while the Synchronize lock and unlock process is managed by the JVM

2. When a thread acquires a lock using synchronize, if the lock is occupied by another thread, it can now be blocked until the lock is successfully acquired. Lock provides a more flexible way of timing out locks and interrupts, providing a mechanism for exiting without acquiring a lock.

3. A lock can have more than one condition instance, that is, there are multiple conditional queues, and synchronize only a one-way condition queue, the same condition also provides a flexible blocking method, before the notification can be not notified through the interrupt thread and set the waiting time limit, etc. to exit the condition queue.

4. Synchronize synchronization of threads only provides exclusive mode, and lock can provide exclusive mode or share mode

The implementation principle of lock in Java and contract

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.