java并发(六)lock、Condition

本文介绍了Java中解决多线程安全的几种方式,包括synchronized同步代码块和同步方法,以及JDK1.5后的Lock接口实现。对比了synchronized与Lock的异同,指出synchronized自动释放锁而Lock需要手动lock和unlock。详细讲解了ReentrantLock的Condition如何实现线程间的等待和唤醒,并通过生产者消费者问题展示了其实战应用。
摘要由CSDN通过智能技术生成

持续更新。。。。。。

解决多线程安全的几种方式

synchronized 隐式锁
1、同步代码块
在这里插入图片描述
在实现Runnable接口创建多线程的方式中,可以考虑用this充当锁
在继承Thread类创建多线程的方式中慎用this充当监视器,考虑用当前类充当监视器
Runnable
在这里插入图片描述在这里插入图片描述
继承thread类同步代码块
在这里插入图片描述
2、同步方法
3、jdk1.5后 同步锁lock 显示加锁释放锁 释放锁在finally中

用法

在这里插入图片描述
ReentrantLock类实现了Lock
代码:
在这里插入图片描述

面试题:synchronized 与 Lock的异同

相同:二者都可以解决线程安全问题
不同:synchronized在执行相应的同步代码后,自动释放锁
Lock需要手动的启动同步(lock(),同时结束同步也需要手动的实现unlock()

Condition

synchronized可以配合waitnotify实现线程在条件不满足时等待,条件满足时唤醒,
ReentrantLock使用Condition对象实现waitnotify的功能
代码:
使用Condition时,引用的Condition对象必须从Lock实例的newCondition返回。

class TaskQueue {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private Queue<String> queue = new LinkedList<>();

    public void addTask(String s) {
        lock.lock();
        try {
            queue.add(s);
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public String getTask() {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                condition.await();
            }
            return queue.remove();
        } finally {
            lock.unlock();
        }
    }
}

await()释放当前锁,进入等待状态
signal()会唤醒某个等待的线程
signalAll()会唤醒所有等待的线程

生产者消费者问题:

生产者比消费者快时,消费者会漏掉一些数据没有取到
消费者比生产者快时,消费者会取相同的数据
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用JUC下的Condition解决虚假唤醒的问题,用于线程通信
在java.util.concurrent包下有更好的解决加锁、等待、通知、释放锁的操作,condition.await(),condition.signal()

参考博客:
https://blog.csdn.net/qq_17079255
https://www.liaoxuefeng.com/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值