Java并发编程十 重入锁ReentrantLock 读写锁ReentrantReadWriteLock

Java并发编程十 重入锁ReentrantLock 读写锁ReentrantReadWriteLock

Java的concurrent并发包提供了一套与Synchronized关键字相同功能Lock,还有与wait()/notify()相同功能的Condition。

Lock的功能比传统的Synchronized更加灵活。它具有嗅探锁定和多路分支等功能(一个lock对象可以创建多个Condition)。

1.Lock和synchronized的区别和各自的特点

1、类型不同
Lock是一个接口,是JDK层面的实现;synchronized是Java的关键字,是JVM层面的实现,是Java的内置特性;这也造成了在锁管理上的不同。
2、释放锁的方式
Lock是在编码中进行锁的操作,需要主动调用接口中的方法释放锁,所以使用Lock时需要配合try模块,在finally中释放锁,不然一旦发生异常很可能造成死锁现象;synchronized由于是JVM层面的实现,获取锁和释放锁的操作是不可见的,当发生异常时,锁的释放由JVM实现。
3、获取锁的过程
Lock接口中提供的方法,让获取锁的过程更加灵活,编程人员可以方便的在获取锁的过程中进行多种操作,比如尝试获取锁、设置获取锁的超时时间、中断等待获取锁的线程等,应该说让锁的操作变得“丰富多彩”起来;synchronized是无法这么灵活的对锁进行操作的。
4、效率
基于读写锁接口的扩展,Lock可以提高多个线程进行读操作的效率,在大并发量的情况下,效率的提高会尤其明显。

2.ReentrantLock

ReentrantLock 重入锁 它与Synchronized关键字的功能相同只是需要自己手动释放锁,而线程间的通信机制wait()/notify()也有相应的代替实现Condition。其原理和Synchronized是一样的。

/**
 * Created by lyyz on 18-5-17.
 */
public class ReentrantLock_eg {

    ReentrantLock reentrantLock = new ReentrantLock();
    Condition condition1 = reentrantLock.newCondition();
    Condition condition2 = reentrantLock.newCondition();


    public void method1(){
        try {
            reentrantLock.lock();
            System.out.println(Thread.currentThread().getName()+"进入mehtod1");
            System.out.println(Thread.currentThread().getName()+"condition1  休眠");
            condition1.await();
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName()+"完成mehtod1");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }

    public void method2(){
        try {
            reentrantLock.lock();
            System.out.println(Thread.currentThread().getName()+"进入mehtod2");
            System.out.println(Thread.currentThread().getName()+"condition2  休眠");
            condition2.await();
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName()+"完成mehtod2");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }

    public void method3(){
        try {
            reentrantLock.lock();
            System.out.println(Thread.currentThread().getName()+"进入mehtod3");
            System.out.println(Thread.currentThread().getName()+"唤醒condition1 休眠状态的线程 ");
            condition1.signal();
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName()+"完成mehtod3");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }

    public void method4(){
        try {
            reentrantLock.lock();
            System.out.println(Thread.currentThread().getName()+"进入mehtod4");
            System.out.println(Thread.currentThread().getName()+"休眠");
            System.out.println(Thread.currentThread().getName()+"唤醒condition2 休眠状态的线程 ");
            condition2.signal();
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName()+"完成mehtod4");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }

    public static void main(String[] args) {
        final ReentrantLock_eg reentrantLock_eg = new ReentrantLock_eg();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                reentrantLock_eg.method1();
            }
        },"t1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                reentrantLock_eg.method2();
            }
        },"t2");

        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                reentrantLock_eg.method3();
            }
        },"t3");

        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                reentrantLock_eg.method4();
            }
        },"t4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        // run output 
//        t1进入mehtod1
//        t1condition1  休眠
//        t2进入mehtod2
//        t2condition2  休眠
//        t3进入mehtod3
//        t3唤醒condition1 休眠状态的线程
//        t3完成mehtod3
//        t1完成mehtod1
//        t4进入mehtod4
//        t4休眠
//        t4唤醒condition2 休眠状态的线程
//        t4完成mehtod4
//        t2完成mehtod2
    }
}

3.ReentrantReadWriteLock

ReentrantReadWriteLock 读写锁,多用于读多写少的情况。它的特点就是 读读共享 写写互斥,读写互斥

/**
 * Created by lyyz on 18-5-17.
 */
public class ReentrantReadWriteLock_eg {
    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    private ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
    private ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();

    public void read(){
        try {
            readLock.lock();
            System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
            Thread.sleep(3000);
            System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readLock.unlock();
        }
    }

    public void write(){
        try {
            writeLock.lock();
            System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
            Thread.sleep(3000);
            System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            writeLock.unlock();
        }
    }

    public static void main(String[] args) {

        ReentrantReadWriteLock_eg reentrantReadWriteLock_eg = new ReentrantReadWriteLock_eg();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                reentrantReadWriteLock_eg.read();
            }
        },"t1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                reentrantReadWriteLock_eg.read();
            }
        },"t2");
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                reentrantReadWriteLock_eg.write();
            }
        },"t3");
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                reentrantReadWriteLock_eg.write();
            }
        },"t4");
        //读读共享,两个线程可同时进行读取
//        t1.start();
//        t2.start();
//        当前线程:t2进入...
//        当前线程:t1进入...
//        当前线程:t2退出...
//        当前线程:t1退出...
        //写写互斥 一个线程执行完以后另一个线程才能执行
//        t3.start();
//        t4.start();
//        当前线程:t3进入...
//        当前线程:t3退出...
//        当前线程:t4进入...
//        当前线程:t4退出...
        //读写互斥
//        t1.start();
//        t3.start();
//        当前线程:t1进入...
//        当前线程:t1退出...
//        当前线程:t3进入...
//        当前线程:t3退出...
    }

}

猜你喜欢

转载自blog.csdn.net/oYueYang1/article/details/80354364