ReentrantLock

  in multithreaded operation. Guarantees the atomicity of a shared resource. The first thing that comes to mind is to use the synchronized keyword

Provide a more flexible and powerful ReentrantLock in jdk5 

Use reentrantLock.lock(); to acquire the lock Use reentrantLock.unlock(); to release the lock

public class ReentrantLockTest {
    ReentrantLock reentrantLock = new ReentrantLock();

    public void add(Object data) throws InterruptedException {
        try {
            reentrantLock.lock();
            System.out.println( "Simulation add time" );
            Thread.sleep(2000);
            System.out.println( "Adding completed" );
        } finally {
            // TODO: handle finally clause
            reentrantLock.unlock();
        }

    }

    public void get() throws InterruptedException {
        
        try {
            reentrantLock.lock();
            System.out.println( "Simulate acquisition" );
            Thread.sleep(1000);
            System.out.println( "Adding completed" );
        } finally {
            // TODO: handle finally clause
            reentrantLock.unlock();
        }
    }
    public static void main(String[] args) {
        final ReentrantLockTest reentrantLockTest=new ReentrantLockTest();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    reentrantLockTest.add(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    reentrantLockTest.get();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }).start();;
    }

The difference between synchronized and ReentrantLock

1.synchronized is handed over to the jvm to schedule. ReentrantLock is controlled by java code

2. Synchronized will greatly reduce performance when many threads compete. ReentrantLock will not compete with many threads.

3.ReentrantLock must cooperate with finally, otherwise it is easy to cause deadlock

4.synchronized can only be synchronized in a method block. ReentrantLock can span methods

ReentrantLock reentrantLock = new ReentrantLock();

    public void Test1() {
        reentrantLock.lock();
        /*
         * execute logic
        */
        Test2 ();
    }
    public  void Test2 () {
        reentrantLock.unlock();
    }

5. ReentrantLock can perform fair lock selection

When to choose ReentrantLock

1. A thread needs to interrupt tryLock while waiting for control of a lock

public class ReentrantLockTest {
    ReentrantLock reentrantLock = new ReentrantLock();

    public void add(Object data) throws InterruptedException {
        try {
            reentrantLock.lock();
            
            Thread.sleep(10000);
            System.out.println( "Simulation add time" );
        
        } finally {
            // TODO: handle finally clause
            reentrantLock.unlock();
        }

    }

    public void get() throws InterruptedException {
        
        try {
            reentrantLock.tryLock( 1000, TimeUnit.MILLISECONDS); // Try to acquire the lock for 1000 milliseconds and fail to give up 
            System.out.println("simulated acquisition" );
            Thread.sleep(1000);
            System.out.println( "Get complete" );
        } finally {
            // TODO: handle finally clause
            reentrantLock.unlock();
        }
    }
    public static void main(String[] args) {
        final ReentrantLockTest reentrantLockTest=new ReentrantLockTest();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    reentrantLockTest.add(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    reentrantLockTest.get();
                
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println( "Execute other business logic" );
            }
        },"t2").start();;
    }
}

The first thread acquires the lock and waits 5 seconds. When reentrantLock.tryLock(1000, TimeUnit.MILLISECONDS) will try to acquire the lock, if not acquired within 1 second, throw an exception and continue to execute

Print

Simulate acquisition
Acquired Exception in thread "t2" 
java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source)
    at java.util.concurrent.locks.ReentrantLock.unlock(Unknown Source)
    at com.bjsxt.height.concurrent019.ReentrantLockTest.get(ReentrantLockTest.java:32)
    at com.bjsxt.height.concurrent019.ReentrantLockTest$2.run(ReentrantLockTest.java:56)
    at java.lang.Thread.run(Unknown Source)
Simulation of new time-consuming

 


2. Some wait-notify needs to be handled separately. The Condition application in ReentrantLock can control which thread to notify 

public static void main(String[] args) throws InterruptedException {
        final ReentrantLock reentrantLock = new ReentrantLock();
        final Condition condition1= reentrantLock.newCondition();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    reentrantLock.lock();
                    condition1.await();
                    System.out.println( "Thread 1 executes down" );
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }finally {
                    reentrantLock.unlock();
                }
            }
        }).start();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    reentrantLock.lock();
                    Thread.sleep(5000);
                    condition1.signal();
                    
            
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }finally {
                    reentrantLock.unlock();
                }
            }
        },"t2").start();
        Thread.sleep( 2000 );
         // Cancel condition1 waiting 
    }
reentrantLock.newCondition() can be multiple new. All waiting conditions can be awakened by reentrantLock.signalAll()


3. With fair lock function, each incoming thread will wait in line

ReentrantLock reentrantLock = new ReentrantLock(true) is fair

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325234260&siteId=291194637