Java Concurrency: Lock Framework detailed __java

Source: Internet
Author: User
Tags finally block

Java Concurrency: Lock framework Detailed

Summary:

We already know that synchronized is the Java keyword, is the built-in features of Java, in the JVM level to achieve the synchronization of the critical resources of mutually exclusive access, but the synchronized granularity is somewhat large, in dealing with the actual problem there are many limitations, such as response interruption. Lock provides a wider range of lock operations than synchronized, which handles thread synchronization issues in a more elegant manner. Based on the comparison between synchronized and lock, this paper introduces the branch of lock frame in detail in Java, and finally gives some related concepts of lock. I. Limitations of synchronized and the advantages of Lock

Recalling the article "Java Concurrency: Built-in lock Synchronized", if a code block is decorated by the Synchronized keyword, when a thread acquires the corresponding lock and executes the code block, the other threads can only wait until the thread that holds the lock releases the lock. In fact, the threads that hold locks are generally one of the following three situations: the thread that owns the lock executes the block of code, and then releases the possession of the lock; an exception occurs when the lock thread executes, when the JVM makes the thread automatically release the lock, and the lock thread enters the waiting state, For example, call the Wait () method in the thread, and so on.

Synchronized is a built-in feature of the Java language that makes it easy to synchronize mutually exclusive access to critical resources. So why is lock still there? Consider the following three cases: Case 1:
In the case of using the Synchronized keyword, if the thread that owns the lock is blocked by waiting for IO or some other reason (such as invoking the Sleep method), then the other thread will have to wait all the time, and there is no other way. This can greatly affect program execution efficiency. Therefore, there is a mechanism to keep waiting threads from waiting indefinitely (such as just waiting for a certain amount of time (solution: Trylock long, Timeunit unit) or able to respond to interrupts (solution: lockinterruptibly ( )), which can be resolved by Lock. Case 2:
We know that when more than one thread reads and writes a file, there is a conflict between read and write operations, as well as write and write operations, but there is no conflict between read and read operations. However, if you use the Synchronized keyword to achieve synchronization, it will cause a problem, that is, when more than one thread is only read operation, only one thread can read operation, other threads can only wait for the lock release and cannot read operation. Therefore, a mechanism is needed to make the thread not collide when multiple threads are simply read-operated. Similarly, lock can solve this situation (solution: Reentrantreadwritelock). Case 3:
We can tell by lock that the line Chengyu did not get the lock successfully (solution: Reentrantlock), but this is synchronized impossible.

The three cases mentioned above can be solved by lock, but the Synchronized keyword is powerless. In fact, lock is an interface under the Java.util.concurrent.locks package, and the lock implementation provides more flexible, broader, granular lock operations than the Synchronized keyword, which handles thread synchronization issues in a more elegant manner. In other words, Lock provides more functionality than synchronized. However, the following points should be noted:

1) synchronized is a Java keyword, so it is a built-in feature of Java, is based on the JVM level implementation, after compiling, will be in the synchronized block before and after the formation of Monitorenter and monitorexit two byte code instructions , and lock is a Java interface, is based on the JDK level, through this interface can achieve synchronous access;

2 The synchronized mode does not require the user to manually release the lock, when the synchronized method or synchronized code block execution, the system will automatically let the thread release the lock on the occupation, and lock must be the user to manually release the lock (when an exception occurs, Locks are not automatically released, which can lead to deadlocks if there is no active release of the lock.

This is very well understood. The synchronized approach is Java native support, and it is certainly convenient for developers to use it to solve concurrent problems, where developers do not need to manually acquire locks and release locks, which are automatically done by Java itself While lock is an interface provided to developers at the JDK level, developers need to manually acquire and release locks when using it to resolve concurrency problems. two. Common classes and interfaces under the Java.util.concurrent.locks package

The following are the most commonly used classes and interfaces under the Java.util.concurrent.locks package:

           

1, Lock

By looking at lock's source, lock is an interface:

Public interface Lock {
    void lock ();
    void Lockinterruptibly () throws interruptedexception;  Can respond to interrupts
    Boolean trylock ();
    Boolean Trylock (long time, Timeunit unit) throws interruptedexception;  Can respond to interrupt
    void unlock ();
    Condition newcondition ();
}
   
   
    
    1
    
    2
    
    3
    
    4
    
    5
    
    6 7 8
   
   

Each method in the lock interface is parsed individually. Lock (), Trylock (), Trylock (long, Timeunit unit), and lockinterruptibly () are used to acquire locks. The UnLock () method is used to release the lock. Newcondition () returns a new Condition instance bound to this Lock for collaboration between threads, as described in the article "Java Concurrency: Communication and collaboration between threads."

1). Lock ()

Four methods are declared in lock to acquire a lock, so what is the difference between the four methods? First, the lock () method is the most commonly used method, which is used to acquire locks. Waits if the lock has been acquired by another thread. As already mentioned, if you use lock, you must actively release the lock, and when an exception occurs, the lock is not automatically released. Therefore, in general, use lock must be in Try...catch ... block, and the operation of releasing the lock is carried out in the finally block to ensure that the lock must be released to prevent the deadlock from occurring. Usually using lock for synchronization is used in the following form:

Lock lock = ...;
Lock.lock ();
try{
    //Processing Task
}catch (Exception ex) {

}finally{
    lock.unlock ();   Release lock
   
   
    
    1
    
    2
    
    3
    
    4
    
    5
    
    6 7 8 9
   
   

2. Trylock () & Trylock (long time, timeunit)

The Trylock () method has a return value, it represents an attempt to acquire a lock, returns true if it succeeds, or false if a failure was obtained (that is, the lock was acquired by another thread), that is, the method returns immediately (not always waiting there when the lock is not available).

The Trylock (long, Timeunit unit) method is similar to the Trylock () method, except that the method waits for a certain amount of time when the lock is not available, returns False if the lock is not held within the time limit, and can respond to interrupts. Returns true if the lock is obtained at the beginning or during the wait period.

In general, this is done using Trylock to get the lock:

Lock lock = ...;
if (Lock.trylock ()) {
     try{
         //Processing Task
     }catch (Exception ex) {

     }finally{
         lock.unlock ();   Release lock
     } 
}else {
    //if unable to acquire lock, do other things directly
}
   
   
    
    1
    
    2
    
    3
    
    4
    
    5
    
    6 7 8
    
    9
    
    12
   
   

3). lockinterruptibly ()

The lockinterruptibly () method is special, and when the lock is acquired by this method, if the thread is waiting for the lock to be acquired, the thread can respond to the interrupt, that is, the wait state of the disconnected thread. For example, if thread a acquires a lock while thread B is waiting, the Threadb.interrupt () method for thread B can be in the wait process of interrupt thread B when two threads are simultaneously using lock.lockinterruptibly () to acquire a lock.

Because an exception is thrown in the declaration of Lockinterruptibly (), the lock.lockinterruptibly () must be placed in a try block or outside of the method that calls Lockinterruptibly () is thrown Interruptedexception, but recommended use of the latter, explained later. Therefore, the lockinterruptibly () is generally used in the following forms:

public void Method () throws Interruptedexception {
    lock.lockinterruptibly ();
    try {  
     //...
    }
    finally {
        lock.unlock ();
    }  
}
   
   
    
    1
    
    2
    
    3
    
    4
    
    5
    
    6 7 8 9
   
   

Note that when a thread acquires a lock, it is not interrupted by the interrupt () method. Because the interrupt () method only interrupts threads in the blocking process and cannot interrupt threads in the running process. Therefore, when a lock is acquired through the lockinterruptibly () method, if it cannot be obtained, the interrupt can only be responded to in the case of a wait. Compared with synchronized, when a thread is waiting for a lock, it cannot be interrupted, only waiting.

Best practice Practice: When lock is used, whichever way you acquire it, it is customary to place the code that gets the lock on try...catch ... because we typically place the unlock operation of the lock in the finally clause, if the thread does not acquire the lock, When a finally clause is executed, a unlock operation is performed, which throws a illegalmonitorstateexception, because the thread does not acquire a lock but performs an understanding lock operation.

2, Reentrantlock

Reentrantlock, you can enter the lock again. Reentrantlock is the only class that implements the lock interface, and Reentrantlock provides more methods. Here are some examples to learn how to use Reentrantlock.

The correct use of 1:lock case

public class Test {private arraylist<integer> ArrayList = new Arraylist<

    ;integer> ();

        public static void Main (string[] args {final Test test = new test ();
            New Thread ("A") {public void run () {Test.insert (Thread.CurrentThread ());
        };

        }.start ();
            New Thread ("B") {public void run () {Test.insert (Thread.CurrentThread ());
        };
    }.start ();  public void Insert (thread thread) {Lock lock = new Reentrantlock ();
        Note This place: Lock is declared as a local variable lock.lock ();
            try {System.out.println ("thread" + thread.getname () + "got lock ...");
            for (int i = 0; i < 5; i++) {arraylist.add (i); }
        } 

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.