Lock 的使用

205 阅读9分钟

1. ReentrantLock 类

1.1 使用 ReentrantLock 实现同步

public class Service {

    private Lock lock = new ReentrantLock();

    public void testA() {
        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() {
        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() {
        service.testA();
    }
}

public class ThreadB extends Thread {

    private Service service;

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

    @Override
    public void run() {
        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();
    }
}

1.2 使用 Condition 实现等待/通知模式

使用 ReentrantLock 结合 Condition 可以实现“选择性通知”,也就是一个 Lock 对象里可以创建多个 Condition (即对象监视器)实例,线程对象可以注册在指定的 Condition 中,从而可以有选择性的进行线程通知

public class Service {

    private Lock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    public void await() {
        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() {
        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() {
                service.await();
            }
        };
        Thread a = new Thread(run1);

        a.start();
        Thread.sleep(3000);
        service.signal();
    }
}
  • Object 类中的 wait() 方法相当于 Condition 类中的 await() 方法
  • Object 类中的 wait(long timeout) 方法相当于 Condition 类中的 await(long time, TimeUnit unit) 方法
  • Object 类中的 noytify() 方法相当于 Condition 类中的 signal() 方法
  • Object 类中的 noytifyAll() 方法相当于 Condition 类中的 signalAll() 方法

1.3 使用多个 Condition 实现通知部分线程

public class Service {

    private ReentrantLock lock = new ReentrantLock();

    private Condition conditionA = lock.newCondition();

    private Condition conditionB = lock.newCondition();

    public void awaitA() {
        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() {
        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() {
        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() {
        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() {
                service.awaitA();
            }
        };

        Runnable run2 = new Runnable() {
            @Override
            public void run() {
                service.awaitB();
            }
        };

        Thread a = new Thread(run1);
        Thread b = new Thread(run2);
        a.start();
        b.start();

        Thread.sleep(5000);

        service.signalAllA();
//        service.signalAllB();
    }
}

1.4 实现生产者/消费者模式(一对一)

public class Service {

    private ReentrantLock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    private boolean hasValue = false;

    public void set() {
        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() {
        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() {
        while (true) {
            service.get();
        }
    }
}

public class ProducerThread extends Thread {

    private Service service;

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

    @Override
    public void run() {
        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();
    }
}

1.5 实现生产者/消费者模式(多对多)

public class Service {

    private ReentrantLock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    private boolean hasValue = false;

    public void set() {
        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() {
        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() {
        while (true) {
            service.get();
        }
    }
}

public class ProducerThread extends Thread {

    private Service service;

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

    @Override
    public void run() {
        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();
        }
    }
}

1.6 公平锁和非公平锁

  • 公平锁:公平锁表示线程获取锁的顺序是按照加锁的顺序来分配的,即先来先得的 FIFO 先进先出顺序
  • 非公平锁:非公平锁是一种获取锁的抢占机制,是随机获取锁的,这种方式可能造成某些线程一直拿不到锁
public class MyThread extends Thread {

    private ReentrantLock lock;

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

    @Override
    public void run() {
        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();
        }
    }
}

1.7 getHoldCount()、getQueueLength()、getWaitQueueLength() 方法的使用

  • getHoldCount() 方法:查询当前线程保持该锁的个数,也就是调用 lock() 方法的次数

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testA() {
            try {
                lock.lock();
                System.out.println(Thread.currentThread().getName() + " testA() getHoldCount=" + lock.getHoldCount());
                testB();
            } finally {
                lock.unlock();
            }
        }
    
        public void testB() {
            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 = new Service();
            service.testA();
        }
    }
    
  • getQueueLength() 方法:查询正在等待获取该锁的线程数(估计数)

    public class Service {
    
        public ReentrantLock lock = new ReentrantLock();
    
        public void testA() {
            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() {
                    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());
        }
    }
    
  • getWaitQueueLength(Condition condition) 方法:查询等待该锁相关的 Condition 条件的线程数(估计数)

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        private Condition condition = lock.newCondition();
    
        public void await() {
            try {
                lock.lock();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void signal() {
            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() {
                    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();
        }
    }
    

1.8 hasQueuedThread()、hasQueuedThreads()、hasWaiters() 方法的使用

  • hasQueuedThread(Thread thread) 方法:判断指定线程是否等待该锁

  • hasQueuedThreads() 方法:判断该锁是否有线程等待获取

    public class Service {
    
        public ReentrantLock lock = new ReentrantLock();
    
        public void waitMethod() {
            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() {
                    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());
        }
    }
    
  • hasWaiters(Condition condition) 方法:判断是否有线程等待该锁相关的 Condition 条件

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        private Condition condition = lock.newCondition();
    
        public void await() {
            try {
                lock.lock();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void signal() {
            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() {
                    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();
        }
    }
    

1.9 isFair()、isHeldByCurrentThread()、lock.isLocked() 方法的使用

  • isFair() 方法:判断是不是公平锁

    public class Service {
    
        private ReentrantLock lock;
    
        public Service(boolean isFair) {
            this.lock = new ReentrantLock(isFair);
        }
    
        public void testMethod() {
            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() {
                    service.testMethod();
                }
            };
    
            Thread thread = new Thread(runnable);
            thread.start();
        }
    }
    
  • isHeldByCurrentThread() 方法:判断当前线程是否持有该锁

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testMethod() {
            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() {
                    service.testMethod();
                }
            };
    
            Thread thread = new Thread(runnable);
            thread.start();
        }
    }
    
  • lock.isLocked() 方法:判断该锁是否被任意线程持有

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testA() {
            try {
                lock.lock();
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void testB() {
            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() {
                    service.testA();
                }
            };
    
            service.testB();
    
            Thread thread = new Thread(runnable);
            thread.start();
    
            Thread.sleep(50);
            service.testB();
        }
    }
    

1.10 lockInterruptibly()、tryLock()、tryLock(long timeout, TimeUnit unit) 方法的使用

  • lockInterruptibly() 方法:线程准备获取锁时,如果当前线程已被中断,则抛出异常

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testA() {
            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() {
                    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");
        }
    }
    
  • tryLock() 方法:线程如果调用方法时锁未被另一个线程持有,则获取该锁

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testMethod() {
            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() {
                    service.testMethod();
                }
            };
    
            Thread a = new Thread(runnable, "Thread-A");
            Thread b = new Thread(runnable, "Thread-B");
            a.start();
            b.start();
        }
    }
    
  • tryLock(long timeout, TimeUnit unit) 方法:如果该锁在指定时间内没有被另一个线程持有,且当前线程未被中断,则获取该锁

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        public void testMethod() {
            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() {
                    service.testMethod();
                }
            };
    
            Thread a = new Thread(runnable, "Thread-A");
            Thread b = new Thread(runnable, "Thread-B");
            a.start();
            b.start();
        }
    }
    

1.11 awaitUninterruptibly() 方法的使用

  • 线程调用 await() 方法后,此时再调用 interrupt() 方法抛出异常

  • 线程调用 awaitUninterruptibly() 方法后,此时再调用 interrupt() 方法不会抛出异常

    public class Service {
    
        private ReentrantLock lock = new ReentrantLock();
    
        private Condition condition = lock.newCondition();
    
        public void testMethod() {
            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() {
                    service.testMethod();
                }
            };
    
            Thread a = new Thread(runnable);
            a.start();
            a.interrupt();
        }
    }
    

1.12 awaitUntil() 方法的使用

线程在指定时间内未被唤醒,则在指定时间后自动唤醒

public class Service {

    private ReentrantLock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    public void testMethod() {
        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() {
                service.testMethod();
            }
        };

        Thread a = new Thread(runnable);
        a.start();
    }
}

1.13 使用 Condition 实现顺序执行

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() {
                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() {
                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() {
                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();
        }
    }
}

2. ReentrantReadWriteLock 类

ReentrantReadWriteLock 读写锁有读锁(共享锁)和写锁(排它锁)。读锁之间不互斥,写锁之间互斥,读写锁之间互斥

2.1 读读共享

public class Service {

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void testMethod() {
        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() {
                service.testMethod();
            }
        };

        Thread a = new Thread(runnable, "Thread-A");
        Thread b = new Thread(runnable, "Thread-B");
        a.start();
        b.start();
    }
}

2.2 写写互斥

public class Service {

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void testMethod() {
        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() {
                service.testMethod();
            }
        };

        Thread a = new Thread(runnable, "Thread-A");
        Thread b = new Thread(runnable, "Thread-B");
        a.start();
        b.start();
    }
}

2.3 读写互斥

public class Service {

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void readMethod() {
        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() {
        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() {
                service.readMethod();
            }
        };

        Runnable writeRun = new Runnable() {
            @Override
            public void run() {
                service.writeMethod();
            }
        };

        Thread a = new Thread(readRun, "Thread-A");
        Thread b = new Thread(writeRun, "Thread-B");
        a.start();
        b.start();
    }
}

学自《Java多线程编程核心技术》