持续更新。。。。。。
解决多线程安全的几种方式
synchronized
隐式锁
1、同步代码块
在实现Runnable
接口创建多线程的方式中,可以考虑用this
充当锁
在继承Thread
类创建多线程的方式中慎用this充当监视器,考虑用当前类充当监视器
Runnable
继承thread类同步代码块
2、同步方法
3、jdk1.5后 同步锁lock 显示加锁释放锁 释放锁在finally中
用法
ReentrantLock类实现了Lock
代码:
面试题:synchronized 与 Lock的异同
相同:二者都可以解决线程安全问题
不同:synchronized在执行相应的同步代码后,自动释放锁
Lock需要手动的启动同步(lock()
,同时结束同步也需要手动的实现unlock()
)
Condition
synchronized
可以配合wait
和notify
实现线程在条件不满足时等待,条件满足时唤醒,
ReentrantLock
使用Condition
对象实现wait
和notify
的功能
代码:
使用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/