java multithreading -ReentrantLock reentrant lock and use common API

1 ReentrantLock reentrant lock

And keyword synchronization compared with reentrant lock operation display. You need to manually specify when to lock, when the lock is released. Reentrant lock on the flexibility of the logic control is much better than keywords synchronization.

When you exit, you must remember to release the lock, otherwise there would be no opportunity to visit other threads.

Reentrant lock was called reentrant lock because such locks can repeatedly enter. But only if a thread.

//锁定几个就要释放几个
try{
	lock.lock();	
	lock.lock()
}finally{
    lock.unlock();
    lock.unlock();
}

复制代码

Use ReentrantLock object lock () method to acquire the lock using the unlock () method releases the lock.

public class MyLock extends Thread{

    private Lock lock = new ReentrantLock();

    @Override
    public void run(){
        lock.lock();
        for (int i = 0;i<5;i++){
            System.out.println("ThreadName = "+Thread.currentThread().getName() + " " + i);
        }
        lock.unlock();
    }

    public static void main(String[] args) {
        MyLock myLock = new MyLock();
        Thread r = new Thread(myLock);
        Thread r1 = new Thread(myLock);
        Thread r2 = new Thread(myLock);
        r.start();r1.start();r2.start();
    }

}
复制代码

From the results, the current thread execution after completion of the lock to be released, the other threads can continue printing. When the call lock.lock () method, the thread holding the "Object Monitor", fighting again only when other threads wait for a lock to be released.

ReentrantLock several important ways:

  • lock (): obtain a lock if the lock is occupied waiting.
  • lockInterruptibly (): get the lock, but the priority interrupt response.
  • tryLock (): try to get a lock, if successful, returns true; otherwise returns false. This method does not wait to return immediately.
  • unlock (): release the lock.

1.1 fair and unfair lock lock

Lock lock lock into equity and non-equity locks, lock fair representation order thread acquires the lock is locked in order to allocate the thread, that is, first-served basis to FIFO order. Rather than the fair is a way to get to seize the lock mechanism of the lock, the lock is random access to, and fair is not the same as the lock is not necessarily the first to get a lock first, which causes some threads have been unable to get a lock, there 饥饿phenomenon.

Fair lock is good, but to achieve fairness lock system needs to maintain an orderly queue, and thus achieve a fair lock of relatively high cost, poor performance.

Keywords have to produce a non-lock synchronization fair locks.

You can specify the lock fair or not fair lock the constructor of ReentrantLock.

Non-equity lock ReentrantLock used by default.

public class FairLock extends Thread{

    private ReentrantLock lock;

    public FairLock(boolean isFair){
        lock = new ReentrantLock(isFair);
    }

    @Override
    public void run(){
        try{
            lock.lock();
            System.out.println("⭐线程 "+ Thread.currentThread().getName() + "运行");
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        FairLock fairLock = new FairLock(true);
        Thread[] threads = new Thread[10];
        for (int i = 0;i< 10;i++){
            threads[i] = new Thread(fairLock);
        }
        Arrays.stream(threads).forEach(thread -> thread.start());
    }

}
复制代码

operation result

⭐线程 Thread-1运行
⭐线程 Thread-4运行
⭐线程 Thread-3运行
⭐线程 Thread-2运行
⭐线程 Thread-5运行
⭐线程 Thread-6运行
⭐线程 Thread-7运行
⭐线程 Thread-8运行
⭐线程 Thread-9运行
⭐线程 Thread-10运行
复制代码

Print essentially ordered, that's fair locks. If the parameter to false, then the printed result is substantially scrambled.

⭐线程 Thread-1运行
⭐线程 Thread-4运行
⭐线程 Thread-2运行
⭐线程 Thread-5运行
⭐线程 Thread-3运行
⭐线程 Thread-10运行
⭐线程 Thread-8运行
⭐线程 Thread-7运行
⭐线程 Thread-9运行
⭐线程 Thread-6运行
复制代码

1.2 getHoldCount () method

Role getHoldCount () method is the number of queries the current thread holds this lock, that is, the number of calls lock () method.

public class MyGetHoldCount {

    private ReentrantLock lock = new ReentrantLock();
    public void serviceLock1(){
        try {
            lock.lock();
            System.out.println("serviceLock1 :" + lock.getHoldCount());
            this.serviceLock2();
        }finally {
            lock.unlock();
        }
    }

    public void serviceLock2(){
        try {
            lock.lock();
            System.out.println("serviceLock2 :" + lock.getHoldCount());
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        new MyGetHoldCount().serviceLock1();
    }
}
复制代码

Print output

serviceLock1 :1
serviceLock2 :2
复制代码

1.3 getQueueLength () method

Role getQueueLength () method that returns the number of threads waiting to acquire this lock.

public class MyQueueLen {
    public ReentrantLock lock = new ReentrantLock();

    public void serviceMe(){
        try {
            lock.lock();
            System.out.println("ThreadName = "+ Thread.currentThread().getName() + "获取锁");
            Thread.sleep(Integer.MAX_VALUE);
        }catch (InterruptedException e){
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyQueueLen myQueueLen = new MyQueueLen();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                myQueueLen.serviceMe();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0;i<10;i++){
            threads[i] = new Thread(runnable);
        }
        Arrays.stream(threads).forEach(thread -> thread.start());
        Thread.sleep(1000);
        System.out.println("有" + myQueueLen.lock.getQueueLength() + "个线程在等待锁");
    }
}
复制代码

Print output

ThreadName = Thread-0获取锁
有9在等待锁
复制代码

1.4 hasQueueThread () 方法

The role of boolean hasQueueThread (Thread thread) is whether the query specified thread is waiting to acquire this lock.

The role of boolean hasQueueThreads () is a query whether any threads are waiting to acquire this lock.

public class MyHasQTh {

    public ReentrantLock lock = new ReentrantLock();

    public void serviceMeth(){
        try{
            lock.lock();
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyHasQTh myHasQTh = new MyHasQTh();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                myHasQTh.serviceMeth();
            }
        };
        Thread threadA = new Thread(runnable);
        threadA.start();
        Thread.sleep(1000);
        Thread threadB = new Thread(runnable);
        threadB.start();
        Thread.sleep(500);
        System.out.println(myHasQTh.lock.hasQueuedThread(threadA));
        System.out.println(myHasQTh.lock.hasQueuedThread(threadB));
        System.out.println(myHasQTh.lock.hasQueuedThreads());

    }
}
复制代码

Print results

false
true
true
复制代码

1.5 isFai () method

IsFair action () method is to determine the lock is not fair

public class IsFair {
    private ReentrantLock lock;
    public IsFair(boolean fair){
        lock = new ReentrantLock(fair);
    }
    public void serviceMeth(){
        try {
            lock.lock();
            System.out.println("是否是公平锁:" + lock.isFair());
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        IsFair isFair = new IsFair(true);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                isFair.serviceMeth();
            }
        };
        new Thread(runnable).start();
    }
}
复制代码

Print results

是否是公平锁:true
复制代码

1.6 isHeldByCurrentThread()方法

The role of boolean isHeldByCurrentThread () method is to query whether the current thread to keep this lock.

public class MyHeldThread {

    private ReentrantLock lock;

    public MyHeldThread(boolean fair){
        lock = new ReentrantLock(fair);
    }

    public void serviceMethod(){
        try{
            System.out.println(lock.isHeldByCurrentThread());
            lock.lock();
            System.out.println(lock.isHeldByCurrentThread());
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        MyHeldThread myHeldThread = new MyHeldThread(true);
        new Thread(new Runnable() {
            @Override
            public void run() {
                myHeldThread.serviceMethod();
            }
        }).start();
    }
}
复制代码

Print results

false
true
复制代码

1.7 isLocked () method

The role of Boolean isLocked () method is to query this lock is held by any thread.

public class MyIsLocked {

    public ReentrantLock lock = new ReentrantLock();

    public void serviceMethod(){
        try{
            System.out.println(lock.isLocked());
            lock.lock();
            System.out.println(lock.isLocked());
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        MyIsLocked myIsLocked = new MyIsLocked();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myIsLocked.serviceMethod();
            }
        }).start();
    }
}
复制代码

Print results

false
true
复制代码

1.8 tryLock () method

The role of boolean tryLock () method is invoked only when the lock is not held by another thread of the case returns true, if the lock is held in order to return false. And is executed immediately, not wait.

tryLock is an important way to prevent self-locking.

public class MyTryLock {

    public ReentrantLock lock = new ReentrantLock();

    public void serviceMethod(){
        try {
            if (lock.tryLock()) {
                System.out.println(Thread.currentThread().getName() + "获取锁定 "+System.currentTimeMillis());
                Thread.sleep(4000);
            } else {
                System.out.println(Thread.currentThread().getName() + "未获取锁定");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        MyTryLock myTryLock = new MyTryLock();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                myTryLock.serviceMethod();
            }
        };
        Thread aa = new Thread(runnable, "aa");
        aa.start();
        Thread bb = new Thread(runnable, "bb");
        bb.start();
    }
}

复制代码

Print Results:

aa未获取锁定
bb获取锁定 1560237476296
复制代码

The role of boolean tryLock (long timeout, TimeUnit unit) If the lock is not held by another thread within the given waiting time and the current thread has not been interrupted, then get the lock.

Waits to obtain a lock within a specified time.

public class MyTryLock {

    public ReentrantLock lock = new ReentrantLock();

    public void serviceMethod(){
        try {
            if (lock.tryLock(3,TimeUnit.SECONDS)) {
                System.out.println(Thread.currentThread().getName() + "获取锁定 "+System.currentTimeMillis());
                Thread.sleep(2000);
            } else {
                System.out.println(Thread.currentThread().getName() + "未获取锁定");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        MyTryLock myTryLock = new MyTryLock();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis());
                myTryLock.serviceMethod();
            }
        };
        Thread aa = new Thread(runnable, "aa");
        aa.start();
        Thread bb = new Thread(runnable, "bb");
        bb.start();
    }
}
复制代码

Print Results:

aa 1560237873563
bb 1560237873563
bb获取锁定 1560237873563
aa获取锁定 1560237875579
复制代码

If the Thread.sleep code () to more than 3 seconds time, is printed:

aa 1560237942950
bb 1560237942950
bb获取锁定 1560237942950
aa未获取锁定
复制代码

1.9 getWaitQueueLength()方法

Role int getWaitQueueLength (Condition con) method is to return the number of threads waiting for the lock associated with this Condition is given. That is, the number of instances specified in Condition waiting for this lock.

public class MyWaitQuere {

    public ReentrantLock lock = new ReentrantLock();
    public Condition con = lock.newCondition();

    public void waitMethod(){
        try{
            lock.lock();
            con.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void signalMethod(){
        try{
            lock.lock();
            System.out.println("有 " + lock.getWaitQueueLength(con) + "个线程正在等待con");
            con.signal();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyWaitQuere myWaitQuere = new MyWaitQuere();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                myWaitQuere.waitMethod();
            }
        };
        Thread[] threads = new Thread[10];
        for(int i = 0;i< 10;i++){
            threads[i] = new Thread(runnable);
        }
        Arrays.stream(threads).forEach(thread -> thread.start());
        Thread.sleep(2000);
        myWaitQuere.signalMethod();
    }
}
复制代码

Print results

有 10个线程正在等待con
复制代码

1.10 int hasWaiters(Condition con)

Role int hasWaiters (Condition con) is the query whether any threads are waiting for conditions associated with this Condition lock.

public class MyHasWaiters {

    public ReentrantLock lock = new ReentrantLock();
    public Condition con = lock.newCondition();
    public void myWait(){
        try{
            lock.lock();
            con.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void hasWaits(){
        try{
            lock.lock();
            System.out.println("是否有线程在等待con : " + lock.hasWaiters(con));
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyHasWaiters myHasWaiters = new MyHasWaiters();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myHasWaiters.myWait();
            }
        }).start();
        Thread.sleep(2000);
        myHasWaiters.hasWaits();
    }
}
复制代码

Print results

是否有线程在等待con : true
复制代码

1.11 lockInterruptibly()方法

Role void lockInterruptibly () method is that if the current thread has not been interrupted acquire a lock, then throw an exception has been interrupted.

public class MyLockInterr {

    public ReentrantLock lock = new ReentrantLock();
    public void waitMethod(){
        try{
            lock.lockInterruptibly();
            System.out.println("lock begin " + Thread.currentThread().getName());
            for (int i = 0;i< Integer.MAX_VALUE;i++){new String();}
            System.out.println("lock end " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyLockInterr myLockInterr = new MyLockInterr();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                myLockInterr.waitMethod();
            }
        };
        Thread aaa = new Thread(runnable, "aaa");
        Thread bbb = new Thread(runnable, "bbb");
        aaa.start();
        Thread.sleep(500);
        bbb.start();
        bbb.interrupt();
        System.out.println("main end");
    }
}
复制代码

Print results

lock begin aaa
lock end aaa
java.lang.InterruptedException
main end
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
	at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
	at com.wtj.lock.MyLockInterr.waitMethod(MyLockInterr.java:16)
	at com.wtj.lock.MyLockInterr$1.run(MyLockInterr.java:34)
	at java.lang.Thread.run(Thread.java:748)
复制代码

If lock.lockInterruptibly () instead lock.lock () is not an error.

2 Condition achieve waiting / notification

synchronization, wait (), and notfiy () / notifyAll () method may be implemented in conjunction with wait / notification mode based ReentrantLock same function can be achieved, but the need to use objects Condition, Condition better flexibility, such as multi-channel notification and other functions, is in a lock object can create multiple Condition (ie object monitors) instance, thread object can be registered in the specified Condition, so that there can be thread notifies choice, more flexibility in scheduling.

Lock and synchronization equivalent to the entire object only a single instance of Condition, all threads are registered in this one instance.

Condition class using the await () method allows a thread to wait while releasing the lock current. Using the signal () wake-up method.

Before using Condition instance methods need to remain locked. Lock.lock ()

Condition implementation using multiple threads notification section

public class MyCondition {

    private ReentrantLock lock = new ReentrantLock();
    private Condition con1 = lock.newCondition();
    private Condition con2 = lock.newCondition();

    public void await1(){
        try{
            lock.lock();
            System.out.println("await1 start : "+ System.currentTimeMillis() + " " + Thread.currentThread().getName());
            con1.await();
            System.out.println("await1 end : "+ System.currentTimeMillis() + " " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void await2(){
        try{
            lock.lock();
            System.out.println("await2 start : "+ System.currentTimeMillis() + " " + Thread.currentThread().getName());
            con2.await();
            System.out.println("await2 end : "+ System.currentTimeMillis() + " " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void signalAll_1(){
        try{
            lock.lock();
            System.out.println("signalAll_1 start : "+ System.currentTimeMillis() + " " + Thread.currentThread().getName());
            con1.signalAll();
        }finally {
            lock.unlock();
        }
    }

    public void signalAll_2(){
        try{
            lock.lock();
            System.out.println("signalAll_2 start : "+ System.currentTimeMillis() + " " + Thread.currentThread().getName());
            con2.signalAll();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyCondition myCondition = new MyCondition();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myCondition.await1();
            }
        }, "aaa").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myCondition.await2();
            }
        },"bbb").start();
        Thread.sleep(3000);
        myCondition.signalAll_1();
    }
}
复制代码

Print results

await1 start : 1560238945661 aaa
await2 start : 1560238945661 bbb
signalAll_1 start : 1560238948666 main
await1 end : 1560238948666 aaa
复制代码

From the output results, only to be awakened thread aaa.

3 ReentrantReadWriteLock类

ReentrantLock class with full mutual exclusion effect, that only one thread at the same time to perform tasks after the lock () method. Although this can guarantee thread-safe, but the efficiency is very low.

ReentrantReadWriteLock the JDK is provided a class, which can speed up the operating efficiency, the method need not operate in some instance variables, read-write lock may be used to improve efficiency ReentrantReadWriteLock class.

Read-Write Lock ReentrantReadWriteLock has two locks, a lock is associated with a read operation, also called shared lock ; a write operation is associated lock, also known as an exclusive lock . Read more not mutually exclusive lock, exclusive write locks and read locks, write locks and write locks are mutually exclusive .

3.1 Read Share

public class MyReadLock {

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void read(){
        try{
            lock.readLock().lock();     //读锁锁定
            System.out.println("获取读锁" + Thread.currentThread().getName()+ " "+ System.currentTimeMillis());
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.readLock().unlock();
        }
    }

    public static void main(String[] args) {
        MyReadLock myReadLock = new MyReadLock();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myReadLock.read();
            }
        },"aaa").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myReadLock.read();
            }
        },"bbb").start();
    }
}
复制代码

Print results

获取读锁aaa 1560241121534
获取读锁bbb 1560241121534
复制代码

As can be seen from the results of two threads simultaneously into the lock () code method, read locks described allows multiple threads to simultaneously execute lock () code method.

3.2 Write mutually exclusive

public class MyWriteLock {

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void write(){
        try{
            lock.writeLock().lock();        //写锁锁定
            System.out.println("获得写锁"+ Thread.currentThread().getName() + " " + System.currentTimeMillis());
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.writeLock().unlock();
        }
    }

    public static void main(String[] args) {
        MyWriteLock myWriteLock = new MyWriteLock();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myWriteLock.write();
            }
        },"aaa").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myWriteLock.write();
            }
        },"bbb").start();
    }
}
复制代码

Print results

获得写锁aaa 1560241405832
获得写锁bbb 1560241409834
复制代码

It can be seen after four seconds to perform aaa bbb threads in the thread before entering, indicating that write the same time lock allows only one thread execution lock () method after.

3.3 read lock mutex

public class MyReadWriteLock {

    public ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read(){
        try{
            lock.readLock().lock();
            System.out.println("获取读锁 " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.readLock().unlock();
        }
    }
    public void write(){
        try{
            lock.writeLock().lock();
            System.out.println("获取写锁 " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.writeLock().unlock();
        }
    }

    public static void main(String[] args) {
        MyReadWriteLock myReadWriteLock = new MyReadWriteLock();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myReadWriteLock.read();
            }
        },"aaa").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                myReadWriteLock.write();
            }
        },"bbb").start();
    }
}
复制代码

Print results

获取读锁 aaa 1560241741764
获取写锁 bbb 1560241745770
复制代码

Reproduced in: https: //juejin.im/post/5d075878518825710d2b2471

Guess you like

Origin blog.csdn.net/weixin_34101784/article/details/93174275