(四) 多线程Lock使用

1.ReentrantLock

调用ReentrantLock对象的lock() 方法获取锁,调用unlock() 方法释放锁。

(1) 使用Condition实现等待/通知

synchronized关键字使用wait() 和 notify() / notifyAll() 方法相结合可以实现等待/通知模式,ReentrantLock类也可以实现同样的功能,但需要借助于 Condition对象。 Condition类有更好的灵活性,比如可以实现多路通知功能,线程对象可以注册在指定的Condition中,从而可以有选择性地进行线程通知,在调度线程上更加灵活。而使用 notify() /notifyAll() 方法进行通知时,被通知的线程却是由JVM随机选择的。
线程执行 notifyAll() 时,需要通知所有的WAITING线程,没有选择权,会出现相当大的效率问题。

public class Service {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    ...
    public void await() {
        try {
            lock.lock();
            System.out.println("await开始时间:" + System.currentTimeMillis());
            condition.await();
            System.err.println("await结束时间:" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void signal() {
        try {
            lock.lock();
            System.out.println("signal唤醒时间:" + System.currentTimeMillis());
            condition.signal();
        } finally {
            lock.unlock();
        }
    }
}

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

public class RunMain {
    public static void main(String[] args) throws InterruptedException {
        Service service = new Service();
        ThreadIX thread = new ThreadIX(service);
        thread.start();
        Thread.sleep(3000);
        service.signal();
    }
}

运行结果:
在这里插入图片描述

成功实现等待/通知模式:
Object 类中的wait() 方法相当于 Condition类中的await() 方法。
Object 类中的 wait(long timeout)方法相当于 Condition类中的 await(long time, TimeUnit unit)方法。
Object 类中的 notify() 方法相当于 Condition类中的 signal() 方法。
Object 类中的 notifyAll() 方法相当于 Condition类中的 signalAll() 方法。

2. ReentrantReadWriteLock

ReentrantLock类具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock() 方法后面的任务。这样做虽然保证了实例变量的线程安全性,但效率却是非常低的。
ReentrantReadWriteLock类可以加快运行效率。读写锁有两个锁:一个是读操作相关的共享锁;另一个是写操作相关的排他锁。(多个读锁之间不互斥,读锁与写锁、写锁与写锁之间互斥)即多个 Thread可以同时进行读取操作,但是同一时刻只允许一个 Thread进行写入操作。

public class Service {
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void threadLock() {
        try {
            lock.readLock().lock();
            System.out.println("读锁" + Thread.currentThread().getName()+" : " + System.currentTimeMillis());
            Thread.sleep(2000);
            System.err.println("结束时间:"+System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.readLock().unlock();
        }
    }
}

public class ThreadIX extends Thread {
    private Service service;
    public ThreadIX(Service service) {
        this.service = service;
    }
    @Override
    public void run() {
        service.threadLock();
    }
}

public class RunMain {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadIX threadA = new ThreadIX(service);
        threadA.setName("A");
        threadA.start();
        ThreadIX threadB = new ThreadIX(service);
        threadB.setName("B");
        threadB.start();
    }
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值