1. The class already

1.1 Use ReentrantLock for synchronization

public class Service {

    private Lock lock = new ReentrantLock();

    public void testA(a) {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " testA begin time=" + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println(Thread.currentThread().getName() + " testA begin time=" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}public void testB(a) {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " testB begin time=" + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println(Thread.currentThread().getName() + " testB begin time=" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}}public class ThreadA extends Thread {

    private Service service;

    public ThreadA(Service service) {
        this.service = service;
    }

    @Override
    public void run(a) { service.testA(); }}public class ThreadB extends Thread {

    private Service service;

    public ThreadB(Service service) {
        this.service = service;
    }

    @Override
    public void run(a) { service.testB(); }}public class Test {

    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("Thread-A");
        ThreadA aa = new ThreadA(service);
        aa.setName("Thread-AA");
        ThreadB b = new ThreadB(service);
        b.setName("Thread-B");
        ThreadB bb = new ThreadB(service);
        bb.setName("Thread-BB"); a.start(); aa.start(); b.start(); bb.start(); }}Copy the code

1.2 Use Condition to implement the wait/notification pattern

Using ReentrantLock in conjunction with conditions allows for “selective notification”, which means that multiple instances of conditions (object monitors) can be created within a Lock object, and thread objects can be registered in a given Condition. This allows for selective thread notifications

public class Service {

    private Lock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    public void await(a) {
        try {
            lock.lock();
            System.out.println("await begin time=" + System.currentTimeMillis());
            condition.await();
            System.out.println("await end time=" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}public void signal(a) {
        try {
            lock.lock();
            System.out.println("signal begin time=" + System.currentTimeMillis());
            condition.signal();
            System.out.println("signal end time=" + System.currentTimeMillis());
        } finally{ lock.unlock(); }}}public class Test {

    public static void main(String[] args) throws InterruptedException {
        final Service service = new Service();

        Runnable run1 = new Runnable() {
            @Override
            public void run(a) { service.await(); }}; Thread a =new Thread(run1);

        a.start();
        Thread.sleep(3000); service.signal(); }}Copy the code
  • In the Object classwait()Method equivalent to the Condition classawait()methods
  • In the Object classwait(long timeout)Method equivalent to the Condition classawait(long time, TimeUnit unit)methods
  • In the Object classnoytify()Method equivalent to the Condition classsignal()methods
  • In the Object classnoytifyAll()Method equivalent to the Condition classsignalAll()methods

1.3 Use multiple conditions to implement notification of partial threads

public class Service {

    private ReentrantLock lock = new ReentrantLock();

    private Condition conditionA = lock.newCondition();

    private Condition conditionB = lock.newCondition();

    public void awaitA(a) {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " awaitA begin time=" + System.currentTimeMillis());
            conditionA.await();
            System.out.println(Thread.currentThread().getName() + " awaitA end time=" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}public void awaitB(a) {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " awaitB begin time=" + System.currentTimeMillis());
            conditionB.await();
            System.out.println(Thread.currentThread().getName() + " awaitB end time=" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}public void signalAllA(a) {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " signalAllA begin time=" + System.currentTimeMillis());
            conditionA.signalAll();
            System.out.println(Thread.currentThread().getName() + " signalAllA end time=" + System.currentTimeMillis());
        } finally{ lock.unlock(); }}public void signalAllB(a) {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " signalAllB begin time=" + System.currentTimeMillis());
            conditionB.signalAll();
            System.out.println(Thread.currentThread().getName() + " signalAllB end time=" + System.currentTimeMillis());
        } finally{ lock.unlock(); }}}public class Test {

    public static void main(String[] args) throws InterruptedException {
        final Service service = new Service();

        Runnable run1 = new Runnable() {
            @Override
            public void run(a) { service.awaitA(); }}; Runnable run2 =new Runnable() {
            @Override
            public void run(a) { service.awaitB(); }}; Thread a =new Thread(run1);
        Thread b = new Thread(run2);
        a.start();
        b.start();

        Thread.sleep(5000);

        service.signalAllA();
// service.signalAllB();}}Copy the code

1.4 Realization of producer/consumer model (one to one)

public class Service {

    private ReentrantLock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    private boolean hasValue = false;

    public void set(a) {
        try {
            lock.lock();
            if (hasValue) {
                condition.await();
            }
            System.out.println(Thread.currentThread().getName() + " set");
            hasValue = true;
            condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}public void get(a) {
        try {
            lock.lock();
            if(! hasValue) { condition.await(); } System.out.println(Thread.currentThread().getName() +" get");
            hasValue = false;
            condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}}public class ConsumerThread extends Thread {

    private Service service;

    public ConsumerThread(Service service) {
        this.service = service;
    }

    @Override
    public void run(a) {
        while (true) { service.get(); }}}public class ProducerThread extends Thread {

    private Service service;

    public ProducerThread(Service service) {
        this.service = service;
    }

    @Override
    public void run(a) {
        while (true) { service.set(); }}}public class Test {

    public static void main(String[] args) {
        Service service = new Service();
        ConsumerThread c = new ConsumerThread(service);
        c.setName("Consumer");
        ProducerThread p = new ProducerThread(service);
        p.setName("Producer"); c.start(); p.start(); }}Copy the code

1.5 Realization of producer/consumer model (many-to-many)

public class Service {

    private ReentrantLock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    private boolean hasValue = false;

    public void set(a) {
        try {
            lock.lock();
            while (hasValue) {
                condition.await();
            }
            System.out.println(Thread.currentThread().getName() + " set");
            hasValue = true;
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}public void get(a) {
        try {
            lock.lock();
            while(! hasValue) { condition.await(); } System.out.println(Thread.currentThread().getName() +" get");
            hasValue = false;
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}}public class ConsumerThread extends Thread {

    private Service service;

    public ConsumerThread(Service service) {
        this.service = service;
    }

    @Override
    public void run(a) {
        while (true) { service.get(); }}}public class ProducerThread extends Thread {

    private Service service;

    public ProducerThread(Service service) {
        this.service = service;
    }

    @Override
    public void run(a) {
        while (true) { service.set(); }}}public class Test {

    public static void main(String[] args) {
        Service service = new Service();
        ConsumerThread[] consumerThreads = new ConsumerThread[5];
        ProducerThread[] producerThreads = new ProducerThread[5];
        for (int i = 0; i <5; i++) { consumerThreads[i] =new ConsumerThread(service);
            consumerThreads[i].setName("Consumer-" + i);
            producerThreads[i] = new ProducerThread(service);
            producerThreads[i].setName("Producer-" + i);
        }
        for (int i = 0; i <5; i++) { consumerThreads[i].start(); producerThreads[i].start(); }}}Copy the code

1.6 Fair lock and Unfair Lock

  • Fair lock: Fair lock means that threads acquire locks in the order in which they are locked, i.e., first-come, first-served FIFO order
  • Unfair lock: An unfair lock is a preemption mechanism to acquire a lock. The lock is acquired randomly, which may cause some threads to fail to acquire the lock
public class MyThread extends Thread {

    private ReentrantLock lock;

    public MyThread(ReentrantLock lock) {
        this.lock = lock;
    }

    @Override
    public void run(a) {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " get lock");
        } finally{ lock.unlock(); }}}public class Test {

    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock(true);
// ReentrantLock lock = new ReentrantLock(false);

        MyThread[] myThreads = new MyThread[10];
        for (int i = 0; i <10; i++) { myThreads[i] =new MyThread(lock);
        }
        for (int i = 0; i <10; i++) { myThreads[i].start(); }}}Copy the code

1.7 Use of getHoldCount(), getQueueLength(), and getWaitQueueLength() methods

  • GetHoldCount () method: Queries the number of times the current thread holds the lock, that is, the number of times the lock() method is called

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testA(a) {
            try {
                lock.lock();
                System.out.println(Thread.currentThread().getName() + " testA() getHoldCount=" + lock.getHoldCount());
                testB();
            } finally{ lock.unlock(); }}public void testB(a) {
            try {
                lock.lock();
                System.out.println(Thread.currentThread().getName() + " testB() getHoldCount=" + lock.getHoldCount());
            } finally{ lock.unlock(); }}}public class Test {
    
        public static void main(String[] args) {
            Service service = newService(); service.testA(); }}Copy the code
  • GetQueueLength () method: Queries the number of threads waiting to acquire the lock (estimate)

    public class Service {
    
        public ReentrantLock lock = new ReentrantLock();
    
        public void testA(a) {
            try {
                lock.lock();
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally{ lock.unlock(); }}}public class Test {
    
        public static void main(String[] args) throws InterruptedException {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.testA(); }}; Thread[] threads =new Thread[10];
            for (int i = 0; i <10; i++) { threads[i] =new Thread(runnable);
            }
            for (int i = 0; i <10; i++) { threads[i].start(); } Thread.sleep(500);
            System.out.println("getQueueLength="+ service.lock.getQueueLength()); }}Copy the code
  • GetWaitQueueLength (Condition Condition) method: Query the number of threads waiting for the Condition associated with this lock (estimated)

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        private Condition condition = lock.newCondition();
    
        public void await(a) {
            try {
                lock.lock();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally{ lock.unlock(); }}public void signal(a) {
            try {
                lock.lock();
                System.out.println("getWaitQueueLength=" + lock.getWaitQueueLength(condition));
                condition.signal();
            } finally{ lock.unlock(); }}}public class Test {
    
        public static void main(String[] args) throws InterruptedException {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.await(); }}; Thread[] threads =new Thread[10];
            for (int i = 0; i <10; i++) { threads[i] =new Thread(runnable);
            }
            for (int i = 0; i <10; i++) { threads[i].start(); } Thread.sleep(500); service.signal(); service.signal(); service.signal(); }}Copy the code

1.8 Loves the use of hasQueuedThread(), hasQueuedThreads(), and hasWaiters() methods

  • HasQueuedThread (Thread Thread) method: determines whether the specified Thread is waiting for the lock

  • HasQueuedThreads () method: determines whether there are threads waiting to acquire the lock

    public class Service {
    
        public ReentrantLock lock = new ReentrantLock();
    
        public void waitMethod(a) {
            try {
                lock.lock();
                Thread.sleep(Integer.MAX_VALUE);
            } catch(InterruptedException e) { e.printStackTrace(); }}}public class Test {
    
        public static void main(String[] args) {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.waitMethod(); }}; Thread threadA =new Thread(runnable);
            Thread threadB = new Thread(runnable);
            threadA.start();
            threadB.start();
    
            System.out.println("threadA wait lock? " + service.lock.hasQueuedThread(threadA));
            System.out.println("threadB wait lock? " + service.lock.hasQueuedThread(threadB));
            System.out.println("have thread wait lock? "+ service.lock.hasQueuedThreads()); }}Copy the code
  • HasWaiters (Condition Condition) Method: Check whether there are threads waiting for the Condition Condition associated with this lock

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        private Condition condition = lock.newCondition();
    
        public void await(a) {
            try {
                lock.lock();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally{ lock.unlock(); }}public void signal(a) {
            try {
                lock.lock();
                System.out.println("have thread wait lock condition? " + lock.hasWaiters(condition));
                condition.signal();
            } finally{ lock.unlock(); }}}public class Test {
    
        public static void main(String[] args) throws InterruptedException {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.await(); }}; Thread[] threads =new Thread[10];
            for (int i = 0; i <2; i++) { threads[i] =new Thread(runnable);
            }
            for (int i = 0; i <2; i++) { threads[i].start(); } Thread.sleep(500); service.signal(); service.signal(); service.signal(); }}Copy the code

1.9 Use of isFair(), isHeldByCurrentThread(), and Lock.islocked ()

  • IsFair () method: check whether the lock isFair

    public class Service {
    
        private ReentrantLock lock;
    
        public Service(boolean isFair) {
            this.lock = new ReentrantLock(isFair);
        }
    
        public void testMethod(a) {
            try {
                lock.lock();
                System.out.println("lock isFair=" + lock.isFair());
            } finally{ lock.unlock(); }}}public class Test {
    
        public static void main(String[] args) {
    // final Service service = new Service(false);
            final Service service = new Service(true);
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.testMethod(); }}; Thread thread =newThread(runnable); thread.start(); }}Copy the code
  • The isHeldByCurrentThread() method checks whether the current thread holds the lock

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testMethod(a) {
            try {
                System.out.println(Thread.currentThread().getName() + " held lock? " + lock.isHeldByCurrentThread());
                lock.lock();
                System.out.println(Thread.currentThread().getName() + " held lock? " + lock.isHeldByCurrentThread());
            } finally{ lock.unlock(); }}}public class Test {
    
        public static void main(String[] args) {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.testMethod(); }}; Thread thread =newThread(runnable); thread.start(); }}Copy the code
  • The lock.isLocked() method checks whether the lock is held by any thread

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testA(a) {
            try {
                lock.lock();
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally{ lock.unlock(); }}public void testB(a) {
            System.out.println("locked by any thread? "+ lock.isLocked()); }}public class Test {
    
        public static void main(String[] args) throws InterruptedException {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.testA(); }}; service.testB(); Thread thread =new Thread(runnable);
            thread.start();
    
            Thread.sleep(50); service.testB(); }}Copy the code

1.10 Use of lockInterruptibly(), tryLock(), and tryLock(long timeout, TimeUnit Unit) methods

  • The lockInterruptibly() method: Throws an exception if the current thread is interrupted when the thread is about to acquire the lock

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testA(a) {
            try {
                lock.lockInterruptibly();
    // lock.lock();
                System.out.println("lock begin " + Thread.currentThread().getName());
                for (int i = 0; i < Integer.MAX_VALUE /10; i++) { Math.random(); } System.out.println("lock begin " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                System.out.println("catch enter " + Thread.currentThread().getName());
                e.printStackTrace();
            } finally {
                if(lock.isHeldByCurrentThread()) { lock.unlock(); }}}}public class Test {
    
        public static void main(String[] args) throws InterruptedException {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.testA(); }}; Thread a =new Thread(runnable);
            a.start();
    
            Thread.sleep(500);
    
            Thread b = new Thread(runnable);
            b.start();
            b.interrupt();
    
            System.out.println("main end"); }}Copy the code
  • TryLock () method: a thread obtains the lock if it is not held by another thread when calling the method

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testMethod(a) {
            if (lock.tryLock()) {
                System.out.println(Thread.currentThread().getName() + " get lock");
            } else {
                System.out.println(Thread.currentThread().getName() + " not get lock"); }}}public class Test {
    
        public static void main(String[] args) {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.testMethod(); }}; Thread a =new Thread(runnable, "Thread-A");
            Thread b = new Thread(runnable, "Thread-B"); a.start(); b.start(); }}Copy the code
  • TryLock (long timeout, TimeUnit Unit) method: Obtains the lock if it has not been held by another thread for a specified period of time and the current thread has not been interrupted

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testMethod(a) {
            try {
                if (lock.tryLock(3, TimeUnit.SECONDS)) {
                    System.out.println(Thread.currentThread().getName() + " get lock");
                    Thread.sleep(5000);
    // Thread.sleep(2000);
                } else {
                    System.out.println(Thread.currentThread().getName() + " not get lock"); }}catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if(lock.isHeldByCurrentThread()) { lock.unlock(); }}}}public class Test {
    
        public static void main(String[] args) {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.testMethod(); }}; Thread a =new Thread(runnable, "Thread-A");
            Thread b = new Thread(runnable, "Thread-B"); a.start(); b.start(); }}Copy the code

1.11 Use of the awaitUninterruptibly() method

  • After calling the await() method, the thread calls the interrupt() method to throw an exception

  • Calling interrupt() after the thread has called the awaitUninterruptibly() method does not raise an exception

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        private Condition condition = lock.newCondition();
    
        public void testMethod(a) {
            try {
                lock.lock();
                System.out.println("await begin");
    // condition.await();
                condition.awaitUninterruptibly();
                System.out.println("await end");
            } /*catch (InterruptedException e) { System.out.println("catch enter"); e.printStackTrace(); } * / finally {
                if(lock.isHeldByCurrentThread()) { lock.unlock(); }}}}public class Test {
    
        public static void main(String[] args) {
            final Service service = new Service();
    
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) { service.testMethod(); }}; Thread a =newThread(runnable); a.start(); a.interrupt(); }}Copy the code

1.12 Use of the awaitUntil() method

A thread that is not woken up within the specified time is automatically woken up after the specified time

public class Service {

    private ReentrantLock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    public void testMethod(a) {
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.SECOND, 5);
            lock.lock();
            System.out.println("await begin time=" + System.currentTimeMillis());
            condition.awaitUntil(calendar.getTime());
            System.out.println("await end time=" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}}public class Test {

    public static void main(String[] args) {
        final Service service = new Service();

        Runnable runnable = new Runnable() {
            @Override
            public void run(a) { service.testMethod(); }}; Thread a =newThread(runnable); a.start(); }}Copy the code

1.13 Use Condition for sequential execution

public class Test {

    private static ReentrantLock lock = new ReentrantLock();

    private static Condition conditionA = lock.newCondition();

    private static Condition conditionB = lock.newCondition();

    private static Condition conditionC = lock.newCondition();

    volatile private static int nextWho = 1;

    public static void main(String[] args) {
        Runnable runnable1 = new Runnable() {
            @Override
            public void run(a) {
                try {
                    lock.lock();
                    while(nextWho ! =1) {
                        conditionA.await();
                    }
                    System.out.println(Thread.currentThread().getName() + " run AAAAA");
                    nextWho = 2;
                    conditionB.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally{ lock.unlock(); }}}; Runnable runnable2 =new Runnable() {
            @Override
            public void run(a) {
                try {
                    lock.lock();
                    while(nextWho ! =2) {
                        conditionB.await();
                    }
                    System.out.println(Thread.currentThread().getName() + " run BBBBB");
                    nextWho = 3;
                    conditionC.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally{ lock.unlock(); }}}; Runnable runnable3 =new Runnable() {
            @Override
            public void run(a) {
                try {
                    lock.lock();
                    while(nextWho ! =3) {
                        conditionC.await();
                    }
                    System.out.println(Thread.currentThread().getName() + " run CCCCC");
                    nextWho = 1;
                    conditionA.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally{ lock.unlock(); }}}; Thread[] threadAs =new Thread[5];
        Thread[] threadBs = new Thread[5];
        Thread[] threadCs = new Thread[5];
        for (int i = 0; i <5; i++) { threadAs[i] =new Thread(runnable1, "ThreadA-" + i);
            threadBs[i] = new Thread(runnable2, "ThreadB-" + i);
            threadCs[i] = new Thread(runnable3, "ThreadC-" + i);
        }
        for (int i = 0; i <5; i++) { threadAs[i].start(); threadBs[i].start(); threadCs[i].start(); }}}Copy the code

2. ReentrantReadWriteLock class

ReentrantReadWriteLock Read/write locks Include read locks (shared locks) and write locks (exclusive locks). Read locks are not mutually exclusive, write locks are mutually exclusive, and read and write locks are mutually exclusive

2.1 Read And Share

public class Service {

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void testMethod(a) {
        try {
            lock.readLock().lock();
            System.out.println(Thread.currentThread().getName() + " get readLock time=" + System.currentTimeMillis());
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.readLock().unlock(); }}}public class Test {

    public static void main(String[] args) {
        final Service service = new Service();

        Runnable runnable = new Runnable() {
            @Override
            public void run(a) { service.testMethod(); }}; Thread a =new Thread(runnable, "Thread-A");
        Thread b = new Thread(runnable, "Thread-B"); a.start(); b.start(); }}Copy the code

2.2 Write mutually exclusive

public class Service {

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void testMethod(a) {
        try {
            lock.writeLock().lock();
            System.out.println(Thread.currentThread().getName() + " get writeLock time=" + System.currentTimeMillis());
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.writeLock().unlock(); }}}public class Test {

    public static void main(String[] args) {
        final Service service = new Service();

        Runnable runnable = new Runnable() {
            @Override
            public void run(a) { service.testMethod(); }}; Thread a =new Thread(runnable, "Thread-A");
        Thread b = new Thread(runnable, "Thread-B"); a.start(); b.start(); }}Copy the code

2.3 Read and write are mutually exclusive

public class Service {

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void readMethod(a) {
        try {
            lock.readLock().lock();
            System.out.println(Thread.currentThread().getName() + " get readLock time=" + System.currentTimeMillis());
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.readLock().unlock(); }}public void writeMethod(a) {
        try {
            lock.writeLock().lock();
            System.out.println(Thread.currentThread().getName() + " get writeLock time=" + System.currentTimeMillis());
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ lock.writeLock().unlock(); }}}public class Test {

    public static void main(String[] args) {
        final Service service = new Service();

        Runnable readRun = new Runnable() {
            @Override
            public void run(a) { service.readMethod(); }}; Runnable writeRun =new Runnable() {
            @Override
            public void run(a) { service.writeMethod(); }}; Thread a =new Thread(readRun, "Thread-A");
        Thread b = new Thread(writeRun, "Thread-B"); a.start(); b.start(); }}Copy the code

Learn from “Java Multi-threaded Programming Core Technology”