【Java多线程编程核心技术】第四章 Lock的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_37378518/article/details/85994221

使用ReentrantLock类

Lock lock = new ReentrantLock();
lock.lock();
//同步的代码段
...
lock.unlock();

Condition用法:await(), signal()方法调用之前需要调用lock.lock()获得同步监视器

Lock lock = new ReentrantLock();
Condition condition = new lock.newCondition();

try{
    lock.lock();
    ...
    condition.await();
} catch (...) {
    ...
} finally {
    lock.unlock();
}

try{
    lock.lock();
    ...
    condition.signal();
} finally {
    lock.unlock();
}

使用Condition实现通知部分线程

Lock lock = new ReentrantLock();
Condition conditionA = new lock.newCondition();
Condition conditionB = new lock.newCondition();

//唤醒所有被conditionA.await()等待的线程
conditionA.await(); --> conditionA.signalAll()//唤醒所有被conditionB.await()等待的线程
conditionB.await(); --> conditionB.signalAll()

使用Lock与Condition模拟生产者与消费者

class Service {
    private Lock lock = new ReentrantLock();
    //生产者与消费者使用两个Condition对象
    private Condition conditionPro = lock.newCondition();
    private Condition conditionCon = lock.newCondition();
    private int count = 0;

    public void produce() {
        try {
            //获取锁
            lock.lock();

            //循环生成
            while (true) {
                //使用while循环判断count值
                while (count > 5) {
                    //使生产者等待
                    conditionPro.await();
                }
               /*
                *    // 不能使用 if 对 count 值进行判断
                *    if (count > 5){
                *        conditionPro.await();
                *    }
                *    //使用if后,该生产者会暂时被等待,但可能被其它线程通知
                *    //然后,会继续执行对count的操作
                */
                
                //此处count最大值可达到6
                count++;
                System.out.println("produce---" + count);
                //生产者产生一个值后,count值此时一定 >= 1,可通知消费者
                conditionCon.signalAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //释放锁
            lock.unlock();
        }
    }

    public void consume() {
        try {
            lock.lock();
            while (true) {
                while (count < 1) {
                    conditionCon.await();
                }
                count--;
                System.out.println("consume---" + count);
                conditionPro.signalAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

class Producer extends Thread {
    private Service service;

    Producer(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.produce();
    }
}

class Consumer extends Thread {
    private Service service;

    Consumer(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.consume();
    }
}

公平锁:获取锁的顺序是按照线程加锁的顺序来分配,即FIFO

非公平锁:随机获得锁,该方式可能造成某些线程一直拿不到锁,结果也就是不公平的了

 public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

读写锁ReentrantReadWriteLock的使用

该锁有两个锁,一个是读操作相关的锁,也称共享锁;一个是写操作相关的锁,也叫排他锁。

多个读锁间不互斥,读锁与写锁互斥,写锁与写锁互斥。

多个线程可以同时进行读操作,但同一时刻只允许一个线程进行写操作

ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

lock.readLock().lock();
...
lock.readLock().lock();

猜你喜欢

转载自blog.csdn.net/baidu_37378518/article/details/85994221