使用ReentrantLock类

在Java多线程中,可以使用synchronized关键字来实现线程之间的同步互斥,但在JDK1.5中新增加了ReentrantLock类也能达到同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定、多路分支通知等功能,而且在使用上也比synchronized更加灵活。

使用ReentrantLock实现同步:测试1
public class Service {
    private Lock lock = new ReentrantLock();
    public void testMethod() {
        lock.lock();
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " i=" + (i + 1));
        }
        lock.unlock();
    }
}

public class MyThread extends Thread {
    private Service service;
    public MyThread(Service service) {
        super();
        this.service = service;
    }
    
    @Override
    public void run() {
        service.testMethod();
    }
}

public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        MyThread t1 = new MyThread(service);
        MyThread t2 = new MyThread(service);
        MyThread t3 = new MyThread(service);
        MyThread t4 = new MyThread(service);
        MyThread t5 = new MyThread(service);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}
public class Service {
    private Lock lock = new ReentrantLock();
    public void testMethod() {
        lock.lock();
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " i=" + (i + 1));
        }
        lock.unlock();
    }
}

public class MyThread extends Thread {
    private Service service;
    public MyThread(Service service) {
        super();
        this.service = service;
    }
    
    @Override
    public void run() {
        service.testMethod();
    }
}

public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        MyThread t1 = new MyThread(service);
        MyThread t2 = new MyThread(service);
        MyThread t3 = new MyThread(service);
        MyThread t4 = new MyThread(service);
        MyThread t5 = new MyThread(service);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

控制台打印结果如下:

Thread-3 i=1
Thread-3 i=2
Thread-3 i=3
Thread-3 i=4
Thread-3 i=5
Thread-0 i=1
Thread-0 i=2
Thread-0 i=3
Thread-0 i=4
Thread-0 i=5
Thread-1 i=1
Thread-1 i=2
Thread-1 i=3
Thread-1 i=4
Thread-1 i=5
Thread-2 i=1
Thread-2 i=2
Thread-2 i=3
Thread-2 i=4
Thread-2 i=5
Thread-4 i=1
Thread-4 i=2
Thread-4 i=3
Thread-4 i=4
Thread-4 i=5

可见,当前线程打印完毕之后将锁进行释放,其他线程才可以继续打印。线程打印数据是分组打印,因为当前线程已经持有锁,但线程之间打印的顺序是随机的。


使用ReentrantLock实现同步:测试2
public class Service {
    private Lock lock = new ReentrantLock();
    public void methodA() {
        try {
            lock.lock();
            System.out.println("methodA begin " + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("methodA end " + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void methodB() {
        try {
            lock.lock();
            System.out.println("methodB begin " + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("methodB end " + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}

public class ThreadAA extends Thread {
    private Service service;
    public ThreadAA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}

public class ThreadBB extends Thread {
    private Service service;
    public ThreadBB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}

public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadAA aa = new ThreadAA(service);
        aa.setName("AA");
        aa.start();
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
        ThreadBB bb = new ThreadBB(service);
        bb.setName("BB");
        bb.start();
    }
}
public class Service {
    private Lock lock = new ReentrantLock();
    public void methodA() {
        try {
            lock.lock();
            System.out.println("methodA begin " + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("methodA end " + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void methodB() {
        try {
            lock.lock();
            System.out.println("methodB begin " + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("methodB end " + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}

public class ThreadAA extends Thread {
    private Service service;
    public ThreadAA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}

public class ThreadBB extends Thread {
    private Service service;
    public ThreadBB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}

public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadAA aa = new ThreadAA(service);
        aa.setName("AA");
        aa.start();
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
        ThreadBB bb = new ThreadBB(service);
        bb.setName("BB");
        bb.start();
    }
}

控制台打印结果如下:

methodA begin A time=1467162810185
methodA end A time=1467162815186
methodA begin AA time=1467162815186
methodA end AA time=1467162820187
methodA begin B time=1467162820187
methodA end B time=1467162825187
methodA begin BB time=1467162825187
methodA end BB time=1467162830188

可见,调用lock.lock()代码的线程就持有了“对象监视器”,其他线程只能等待锁被释放时再次争抢。效果和使用synchronized关键字一样,线程之间还是顺序执行的。


使用condition实现等待/通知:错误用法与解决

关键字synchronized与wait()和notify()/notifyAll()方法结合可以实现等待/通知模式,类ReentrantLock也可以实现同样的功能,但需要借助Condition对象。Condition类是在JDK5中出现的技术,使用它有更好的灵活性,比如可以实现多路通知功能,也就是在一个Lock对象里面可以创建多个Condition(即对象监视器)实例,线程对象可以注册在知道的Condition中,从而可以有选择性地进行线程通知,在调度线程上更加灵活。

在使用notify()/notifyAll()方法进行通知时,被通知的线程是由JVM随机选择的。但使用ReentrantLock结合Condition类是可以实现前面介绍过的“选择性通知”,这个功能是非常重要的,而且在Condition类中是默认提供的。

而synchronized就相当于整个Lock对象中只有一个单一的Condition对象,所有的线程都注册在它一个对象的身上。线程开始notifyAll()时,需要通知所有的WAITING线程,没有选择权,会出现相当大的效率问题。

看以下代码:

public class Service {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void await() {
        try {
            condition.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.await();
    }
}

public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.start();
    }
}
public class Service {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void await() {
        try {
            condition.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.await();
    }
}

public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.start();
    }
}

运行以上代码,控制台抛出异常:

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.AbstractQueuedSynchronizer.fullyRelease(Unknown Source)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
    at com.umgsai.thread.thread46.Service.await(Service.java:14)
    at com.umgsai.thread.thread46.ThreadA.run(ThreadA.java:11)

异常信息是监视器出错,解决的办法是必须在condition.await()方法调用之前调用lock.lock()代码获得同步监视器。将Service类做如下修改:

public class Service {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void await() {
        try {
            lock.lock();
            System.out.println("A");
            condition.await();
            System.out.println("B");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            System.out.println("锁被释放了");
        }
    }
}
public class Service {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void await() {
        try {
            lock.lock();
            System.out.println("A");
            condition.await();
            System.out.println("B");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            System.out.println("锁被释放了");
        }
    }
}

重新运行程序,控制台打印结果如下:

A

程序不结束,原因是调用了Condition对象的await()方法,使当前执行任务的线程进入了等待WAITING状态。


正确使用Condition实现等待/通知
public class Service {
    private Lock lock = new ReentrantLock();
    public Condition condition = lock.newCondition();
    public void await() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " await时间为" + System.currentTimeMillis());
            condition.await();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void signal() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " signal时间为" + System.currentTimeMillis());
            condition.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.await();
    };
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.start();
        Thread.sleep(2000);
        service.signal();
    }
}
public class Service {
    private Lock lock = new ReentrantLock();
    public Condition condition = lock.newCondition();
    public void await() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " await时间为" + System.currentTimeMillis());
            condition.await();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void signal() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " signal时间为" + System.currentTimeMillis());
            condition.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.await();
    };
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.start();
        Thread.sleep(2000);
        service.signal();
    }
}

控制台打印结果如下:

Thread-0 await时间为1467293210228
main signal时间为1467293212227

成功实现等待/通知模式。

Object类中的wait()等待相当于Condition类中的await()方法。

Object类中的wait(long timeout)方法相当于Condition类中的await(long time, TimeUnit unit)方法。

Object类中的notify()方法相当于Condition类中的signal()方法。

Object类中的notifyAll()方法相当于Condition类中的signalAll()方法。


使用多个Condition实现通知部分线程:错误用法
public class Service {
    private Lock lock = new ReentrantLock();
    public Condition condition = lock.newCondition();
    public void awaitA() {
        try {
            lock.lock();
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName() + " begin awaitA时间为" + System.currentTimeMillis());
            condition.await();//释放锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end awaitA时间为" + System.currentTimeMillis());
            lock.unlock();
        }
    }
    
    public void awaitB() {
        try {
            lock.lock();
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName() + " begin awaitB时间为" + System.currentTimeMillis());
            condition.await();//释放锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end awaitB时间为" + System.currentTimeMillis());
            lock.unlock();
        }
    }
    
    public void signalAll() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " end signalAll时间为" + System.currentTimeMillis());
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    
    @Override
    public void run() {
        service.awaitA();
    }
}

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    
    @Override
    public void run() {
        service.awaitB();
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
        Thread.sleep(3000);
        service.signalAll();
    }
}

控制台打印结果如下:

A begin awaitA时间为1467293693906
B begin awaitB时间为1467293694407
main end signalAll时间为1467293696406
A end awaitA时间为1467293696906
B end awaitB时间为1467293697407

程序运行后A和B都被唤醒了。


使用多个Condition实现通知部分线程:正确用法

将上面例子中Service作如下修改:

public class Service {
    private Lock lock = new ReentrantLock();
    public Condition conditionA = lock.newCondition();
    public Condition conditionB = lock.newCondition();
    public void awaitA() {
        try {
            lock.lock();
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName() + " begin awaitA时间为" + System.currentTimeMillis());
            conditionA.await();//释放锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end awaitA时间为" + System.currentTimeMillis());
            lock.unlock();
        }
    }
    
    public void awaitB() {
        try {
            lock.lock();
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName() + " begin awaitB时间为" + System.currentTimeMillis());
            conditionB.await();//释放锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end awaitB时间为" + System.currentTimeMillis());
            lock.unlock();
        }
    }
    
    public void signalAll_A() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " end signalAll_A时间为" + System.currentTimeMillis());
            conditionA.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
    public void signalAll_B() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " end signalAll_B时间为" + System.currentTimeMillis());
            conditionB.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
        Thread.sleep(3000);
        service.signalAll_A();//通知在conditionA上等待的线程
        Thread.sleep(2000);
        service.signalAll_B();//通知在conditionB上等待的线程
    }
}
public class Service {
    private Lock lock = new ReentrantLock();
    public Condition conditionA = lock.newCondition();
    public Condition conditionB = lock.newCondition();
    public void awaitA() {
        try {
            lock.lock();
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName() + " begin awaitA时间为" + System.currentTimeMillis());
            conditionA.await();//释放锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end awaitA时间为" + System.currentTimeMillis());
            lock.unlock();
        }
    }
    
    public void awaitB() {
        try {
            lock.lock();
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName() + " begin awaitB时间为" + System.currentTimeMillis());
            conditionB.await();//释放锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end awaitB时间为" + System.currentTimeMillis());
            lock.unlock();
        }
    }
    
    public void signalAll_A() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " end signalAll_A时间为" + System.currentTimeMillis());
            conditionA.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
    public void signalAll_B() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " end signalAll_B时间为" + System.currentTimeMillis());
            conditionB.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
        Thread.sleep(3000);
        service.signalAll_A();//通知在conditionA上等待的线程
        Thread.sleep(2000);
        service.signalAll_B();//通知在conditionB上等待的线程
    }
}

控制台打印结果如下:

A begin awaitA时间为1467293966937
B begin awaitB时间为1467293967437
main end signalAll_A时间为1467293969438
A end awaitA时间为1467293969938
main end signalAll_B时间为1467293971438
B end awaitB时间为1467293971939

实现生产者/消费者模式:一对一交替打印
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("★");
            hasValue = true;
            condition.signal();//通知在condition上等待的线程
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void get() {
        try {
            lock.lock();
            while (!hasValue) {
                condition.await();
            }
            System.out.println("☆");
            hasValue = false;
            condition.signal();//通知在condition上等待的线程
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            service.set();  
        }
    }
}

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            service.get();  
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        ThreadB b = new ThreadB(service);
        a.start();
        b.start();
    }
}
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("★");
            hasValue = true;
            condition.signal();//通知在condition上等待的线程
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void get() {
        try {
            lock.lock();
            while (!hasValue) {
                condition.await();
            }
            System.out.println("☆");
            hasValue = false;
            condition.signal();//通知在condition上等待的线程
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            service.set();  
        }
    }
}

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            service.get();  
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        ThreadB b = new ThreadB(service);
        a.start();
        b.start();
    }
}

控制台打印结果如下:

......
★
☆
★
☆
★
☆
......

将以上代码做如下修改:

public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA[] a = new ThreadA[10];
        ThreadB[] b = new ThreadB[10];
        for (int i = 0; i < 10; i++) {
            a[i] = new ThreadA(service);
            a[i].start();
            b[i] = new ThreadB(service);
            b[i].start();
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA[] a = new ThreadA[10];
        ThreadB[] b = new ThreadB[10];
        for (int i = 0; i < 10; i++) {
            a[i] = new ThreadA(service);
            a[i].start();
            b[i] = new ThreadB(service);
            b[i].start();
        }
    }
}

此时控制台打印结果如下:

......
有可能★连续
☆
★
有可能★连续
☆
有可能☆连续
★
有可能★连续
☆
有可能☆连续
★
有可能★连续
☆
有可能☆连续
有可能☆连续
有可能☆连续
★
有可能★连续
有可能★连续
....

程序运行一段时间后出现假死现象。前面有程序和这个程序的原理一样。解决方法是修改Service里面的condition.signal()为condition.signalAll()。


公平锁与非公平锁
/**
* 公平锁
*/
public class Service {
    private ReentrantLock lock;
    public Service(boolean isFair) {
        super();
        lock = new ReentrantLock(isFair);
    }
    
    public void serviceMethod() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "获得锁定");
        } finally{
            lock.unlock();
        }
    }
}

public class RunFair {
    public static void main(String[] args) {
        final Service service = new Service(true);
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "运行了");
                service.serviceMethod();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();;
        }
    }
}
/**
* 公平锁
*/
public class Service {
    private ReentrantLock lock;
    public Service(boolean isFair) {
        super();
        lock = new ReentrantLock(isFair);
    }
    
    public void serviceMethod() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "获得锁定");
        } finally{
            lock.unlock();
        }
    }
}

public class RunFair {
    public static void main(String[] args) {
        final Service service = new Service(true);
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "运行了");
                service.serviceMethod();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();;
        }
    }
}

控制台打印结果如下:

Thread-0运行了
Thread-1运行了
Thread-0获得锁定
Thread-1获得锁定
Thread-2运行了
Thread-2获得锁定
Thread-3运行了
Thread-4运行了
Thread-3获得锁定
Thread-4获得锁定
Thread-5运行了
Thread-5获得锁定
Thread-6运行了
Thread-8运行了
Thread-6获得锁定
Thread-7运行了
Thread-8获得锁定
Thread-7获得锁定
Thread-9运行了
Thread-9获得锁定

打印结果基本呈有序的状态,这就是公平锁的特点。


getHoldCount方法
/**
 * getHoldCount()方法查询当前线程保持此锁定的个数
 * 也就是调用()方法的次数
 */
public class Service {
    private ReentrantLock lock = new ReentrantLock();
    public void serviceMethod1() {
        try {
            lock.lock();
            System.out.println("serviceMethod1 getHoldCount=" + lock.getHoldCount());//1
            serviceMethod2();
        } finally{
            lock.unlock();
        }
    }
    public void serviceMethod2() {
        try {
            lock.lock();
            System.out.println("serviceMethod2 getHoldCount=" + lock.getHoldCount());//2
        } finally{
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        Service service = new Service();
        service.serviceMethod1();
    }
}

/**
 * getHoldCount()方法查询当前线程保持此锁定的个数
 * 也就是调用()方法的次数
 */
public class Service {
    private ReentrantLock lock = new ReentrantLock();
    public void serviceMethod1() {
        try {
            lock.lock();
            System.out.println("serviceMethod1 getHoldCount=" + lock.getHoldCount());//1
            serviceMethod2();
        } finally{
            lock.unlock();
        }
    }
    public void serviceMethod2() {
        try {
            lock.lock();
            System.out.println("serviceMethod2 getHoldCount=" + lock.getHoldCount());//2
        } finally{
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        Service service = new Service();
        service.serviceMethod1();
    }
}
getQueueLength()方法
//getQueueLength返回正在等待此锁定的线程估计数
public class MyService {
    public ReentrantLock lock = new ReentrantLock();
    public void serviceMethod1() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "进入方法");
            Thread.sleep(Integer.MAX_VALUE);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        final MyService myService = new MyService();
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                myService.serviceMethod1();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        Thread.sleep(2000);
        System.out.println(myService.lock.getQueueLength() + "在等待获取锁");
    }
}
//getQueueLength返回正在等待此锁定的线程估计数
public class MyService {
    public ReentrantLock lock = new ReentrantLock();
    public void serviceMethod1() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "进入方法");
            Thread.sleep(Integer.MAX_VALUE);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        final MyService myService = new MyService();
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                myService.serviceMethod1();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        Thread.sleep(2000);
        System.out.println(myService.lock.getQueueLength() + "在等待获取锁");
    }
}

控制台打印结果如下:

Thread-0进入方法
9在等待获取锁
getWaitQueueLength()方法
public class MyService1 {
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void waitMethod() {
        try {
            lock.lock();
            condition.await();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
    public void notifyMethod() {
        try {
            lock.lock();
            System.out.println(lock.getWaitQueueLength(condition) + "个线程在等待condition");//10
            condition.signal();
            System.out.println(lock.getWaitQueueLength(condition) + "个线程在等待condition");//9
            condition.signal();
            System.out.println(lock.getWaitQueueLength(condition) + "个线程在等待condition");//8
            condition.signalAll();
            System.out.println(lock.getWaitQueueLength(condition) + "个线程在等待condition");//7
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        final MyService1 service = new MyService1();
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        Thread.sleep(2000);
        service.notifyMethod();
    }
}
public class MyService1 {
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void waitMethod() {
        try {
            lock.lock();
            condition.await();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
    public void notifyMethod() {
        try {
            lock.lock();
            System.out.println(lock.getWaitQueueLength(condition) + "个线程在等待condition");//10
            condition.signal();
            System.out.println(lock.getWaitQueueLength(condition) + "个线程在等待condition");//9
            condition.signal();
            System.out.println(lock.getWaitQueueLength(condition) + "个线程在等待condition");//8
            condition.signalAll();
            System.out.println(lock.getWaitQueueLength(condition) + "个线程在等待condition");//7
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        final MyService1 service = new MyService1();
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        Thread.sleep(2000);
        service.notifyMethod();
    }
}

控制台打印结果如下:

10个线程在等待condition
9个线程在等待condition
8个线程在等待condition
0个线程在等待condition

getWaitQueueLength(condition)方法返回等待与此锁定相关的给定条件condition的线程估计数。

public class Service {
    public ReentrantLock lock = new ReentrantLock();
    public Condition condition = lock.newCondition();
    public void waitMethod() {
        try {
            lock.lock();//获得锁
            Thread.sleep(Integer.MAX_VALUE);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        final Service service = new Service();
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread a = new Thread(runnable);
        a.start();
        Thread.sleep(500);
        Thread b = new Thread(runnable);
        b.start();
        Thread.sleep(500);
        System.out.println(service.lock.hasQueuedThread(a));//false 查询指定的线程是否正在等待此锁定
        System.out.println(service.lock.hasQueuedThread(b));//true
        System.out.println(service.lock.hasQueuedThreads());//true 查询是否有线程正在等待此锁
    }
}

public class MyService {
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void waitMethod() {
        try {
            lock.lock();
            condition.await();//进入WAITTING状态,释放锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void notifyMethod() {
        try {
            lock.lock();
            System.out.println("是否有线程正在等待condition:" + lock.hasWaiters(condition));
            System.out.println("正在等待condition的线程数是:" + lock.getWaitQueueLength(condition));//10个线程等待
            condition.signal();//唤醒一个线程
            System.out.println("正在等待condition的线程数是:" + lock.getWaitQueueLength(condition));//9个线程等待
            condition.signalAll();//剩下的个全部唤醒
            System.out.println("正在等待condition的线程数是:" + lock.getWaitQueueLength(condition));//0个线程等待
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        final MyService service = new MyService();
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
            threads[i].start();
        }
        Thread.sleep(2000);
        service.notifyMethod();
    }
}
public class MyService {
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void waitMethod() {
        try {
            lock.lock();
            condition.await();//进入WAITTING状态,释放锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void notifyMethod() {
        try {
            lock.lock();
            System.out.println("是否有线程正在等待condition:" + lock.hasWaiters(condition));
            System.out.println("正在等待condition的线程数是:" + lock.getWaitQueueLength(condition));//10个线程等待
            condition.signal();//唤醒一个线程
            System.out.println("正在等待condition的线程数是:" + lock.getWaitQueueLength(condition));//9个线程等待
            condition.signalAll();//剩下的个全部唤醒
            System.out.println("正在等待condition的线程数是:" + lock.getWaitQueueLength(condition));//0个线程等待
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        final MyService service = new MyService();
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
            threads[i].start();
        }
        Thread.sleep(2000);
        service.notifyMethod();
    }
}

使用Condition实现顺序执行
public class Run {
    volatile private static int nextPrintWho = 1;
    private static ReentrantLock lock = new ReentrantLock();
    final private static Condition conditionA = lock.newCondition();
    final private static Condition conditionB = lock.newCondition();
    final private static Condition conditionC = lock.newCondition();
    public static void main(String[] args) {
        Thread threadA = new Thread(){
            public void run() {
                try {
                    lock.lock();
                    while (nextPrintWho != 1) {
                        conditionA.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadA " + (i + 1));
                    }
                    nextPrintWho = 2;
                    conditionB.signalAll();//唤醒B组
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread threadB = new Thread(){
            public void run() {
                try {
                    lock.lock();
                    while (nextPrintWho != 2) {
                        conditionB.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadB " + (i + 1));
                    }
                    nextPrintWho = 3;
                    conditionC.signalAll();//唤醒C组
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread threadC = new Thread(){
            public void run() {
                try {
                    lock.lock();
                    while (nextPrintWho != 3) {
                        conditionC.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadC " + (i + 1) + " " + System.currentTimeMillis());
                    }
                    nextPrintWho = 1;
                    conditionA.signalAll();//唤醒A组
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread[] aThreads = new Thread[5];
        Thread[] bThreads = new Thread[5];
        Thread[] cThreads = new Thread[5];
        for (int i = 0; i < cThreads.length; i++) {
            aThreads[i] = new Thread(threadA);
            bThreads[i] = new Thread(threadB);
            cThreads[i] = new Thread(threadC);
            aThreads[i].start();
            bThreads[i].start();
            cThreads[i].start();
        }
    }
}
public class Run {
    volatile private static int nextPrintWho = 1;
    private static ReentrantLock lock = new ReentrantLock();
    final private static Condition conditionA = lock.newCondition();
    final private static Condition conditionB = lock.newCondition();
    final private static Condition conditionC = lock.newCondition();
    public static void main(String[] args) {
        Thread threadA = new Thread(){
            public void run() {
                try {
                    lock.lock();
                    while (nextPrintWho != 1) {
                        conditionA.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadA " + (i + 1));
                    }
                    nextPrintWho = 2;
                    conditionB.signalAll();//唤醒B组
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread threadB = new Thread(){
            public void run() {
                try {
                    lock.lock();
                    while (nextPrintWho != 2) {
                        conditionB.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadB " + (i + 1));
                    }
                    nextPrintWho = 3;
                    conditionC.signalAll();//唤醒C组
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread threadC = new Thread(){
            public void run() {
                try {
                    lock.lock();
                    while (nextPrintWho != 3) {
                        conditionC.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadC " + (i + 1) + " " + System.currentTimeMillis());
                    }
                    nextPrintWho = 1;
                    conditionA.signalAll();//唤醒A组
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread[] aThreads = new Thread[5];
        Thread[] bThreads = new Thread[5];
        Thread[] cThreads = new Thread[5];
        for (int i = 0; i < cThreads.length; i++) {
            aThreads[i] = new Thread(threadA);
            bThreads[i] = new Thread(threadB);
            cThreads[i] = new Thread(threadC);
            aThreads[i].start();
            bThreads[i].start();
            cThreads[i].start();
        }
    }
}

控制台输入结果如下:

ThreadA 1
ThreadA 2
ThreadA 3
ThreadB 1
ThreadB 2
ThreadB 3
ThreadC 1 1468067302315
ThreadC 2 1468067302315
ThreadC 3 1468067302315
ThreadA 1
ThreadA 2
ThreadA 3
ThreadB 1
ThreadB 2
ThreadB 3
ThreadC 1 1468067302315
ThreadC 2 1468067302315
ThreadC 3 1468067302315
ThreadA 1
ThreadA 2
ThreadA 3
ThreadB 1
ThreadB 2
ThreadB 3
ThreadC 1 1468067302315
ThreadC 2 1468067302315
ThreadC 3 1468067302315
ThreadA 1
ThreadA 2
ThreadA 3
ThreadB 1
ThreadB 2
ThreadB 3
ThreadC 1 1468067302316
ThreadC 2 1468067302316
ThreadC 3 1468067302316
ThreadA 1
ThreadA 2
ThreadA 3
ThreadB 1
ThreadB 2
ThreadB 3
ThreadC 1 1468067302316
ThreadC 2 1468067302316
ThreadC 3 1468067302316

使用ReentrantReadWriteLock类

ReentrantLock具有完全互斥排他的效果,同一时刻只有一个线程在执行ReentrantLock.lock()方法后面的任务。使用读写锁ReentrantReadWriteLock可以区分读写操作。读操作不互斥时,可以使用读锁让多个线程同时读。写锁互斥时,同一时刻值允许一个线程写。

读读共享
public class Service {
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read() {
        try {
            try {
                lock.readLock().lock();
                System.out.println(Thread.currentThread().getName() + "获得读锁" + System.currentTimeMillis());
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.readLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.read();
    }
}

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.read();
    }
}

public class Run {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        ThreadB b = new ThreadB(service);
        a.start();
        b.start();
    }
}
public class Service {
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read() {
        try {
            try {
                lock.readLock().lock();
                System.out.println(Thread.currentThread().getName() + "获得读锁" + System.currentTimeMillis());
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.readLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.read();
    }
}

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.read();
    }
}

public class Run {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        ThreadB b = new ThreadB(service);
        a.start();
        b.start();
    }
}

程序运行结果如下:

Thread-0获得读锁1468068667767
Thread-1获得读锁1468068667767

可以看出,两个线程同时进入lock()方法后面的代码。


写写互斥

将以上代码的Service类做如下修改:

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

程序运行结果如下:

Thread-0获得写锁1468069134317
Thread-1获得写锁1468069135322

可见此时两个线程以排队方式执行lock()后面的代码。


读写互斥
public class Service {
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read() {
        try {
            try {
                lock.readLock().lock();
                System.out.println(Thread.currentThread().getName() + "获得读锁" + System.currentTimeMillis());
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.readLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void write() {
        try {
            try {
                lock.writeLock().lock();
                System.out.println(Thread.currentThread().getName() + "获得写锁" + System.currentTimeMillis());
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.writeLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.read();
    }
}

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.write();
    }
}

public class Run {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        ThreadB b = new ThreadB(service);
        a.start();
        b.start();
    }
}
public class Service {
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read() {
        try {
            try {
                lock.readLock().lock();
                System.out.println(Thread.currentThread().getName() + "获得读锁" + System.currentTimeMillis());
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.readLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void write() {
        try {
            try {
                lock.writeLock().lock();
                System.out.println(Thread.currentThread().getName() + "获得写锁" + System.currentTimeMillis());
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.writeLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.read();
    }
}

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.write();
    }
}

public class Run {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        ThreadB b = new ThreadB(service);
        a.start();
        b.start();
    }
}

程序运行结果如下:

Thread-0获得读锁1468069343031
Thread-1获得写锁1468069344033

两个线程以排队方式执行lock()后面的代码,可见读写操作是互斥的。

将以上代码做如下修改:

public class Run {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        ThreadB b = new ThreadB(service);
        b.start();//先启动写线程
        a.start();//后启动读线程
    }
}

此时程序运行结果如下:

Thread-1获得写锁1468069625161
Thread-0获得读锁1468069626166

可见,两个线程也是以排队方式执行lock()后面的代码的。

综合ReentrantReadWriteLock类的几个实体程序,“读写” “写写” “写读”都是互斥的。“读读”是异步的,非互斥的。