【JavaEE】线程方法(三):wait-notify锁自定协调、线程安全(一).3:条件产生渡送执行、阻塞队列的解耦通信



目录
一、线程方法(三):wait-notify锁自定协调
知识连接:
抢锁块里进行的 此线程等条件 厌锁欠执行、另线程归条件 醒锁还执行 的锁协调模式
1.实现规格
锁往小里面加,锁协调 占最小的行 就可实现
2.线程欠量
每个线程 最多只能 在欠着一个执行,同方线程 指 同欠等条件方向的多个线程
3.线程塞等
线程 入阻塞地 等待条件,避免了 忙等待 浪费cpu的资源
4.欠等互斥
欠等条件互斥的线程 始终至少有另方 可条件地执行
但可能会因为 唤醒没通知到 它的对立条件可执行线程 而最终 一方条件不符 厌锁入眠 另方条件满足 但缺唤醒 地都在 待唤醒 阻塞中
二、线程安全(一).3:条件产生渡送执行
知识连接:
正确条件 从产生 能渡送到 执行处 的保障实现

1.临执行无缝能改路官口检查
最后的 临执行 无 缝能改路 官口检查,检查正确条件来得被改、错误条件虚假唤醒来得
2.加锁多铺一路上的无缝能改路
唤醒的正确条件产生 到 最后执行的一路 都(加锁成)已无缝能改,唤醒后 到抢到锁后 再到在官口处 直接一定还是原来的正确条件 没改,也就不必 在官口处 去弄检查了
synchronized (this) {
while (size == data.length) {// 2.往后就是最后的 无能修改条件穿插的 临执行 无缝能改路,在官口检查条件
this.wait();// 1.正确条件产生并唤醒它后 经历锁竞争 一路上渡到官口时 条件可能已经改变
}
// 3.官口通过,执行条件:
data[tail] = elem;
tail++;
if (tail == data.length) {
tail = 0;
}
size++;
this.notify();// notify期望唤醒 take中的wait
}
- 渡前官口的二次检查:
渡前检查 筛排送往 要加锁内的 官口检查:
1.execute里面渡前
渡前并发环境下 一次筛排可能的 才拿去送往 加锁开销大的官口检查
2.addWorker里面官口
官口加锁内 二次精确确定地 检查
官路来源:
1.加锁
加锁造官路
2.原子指令
原子指令自带官路
- 渡路上并发读取筛送:
1.加锁官需要
加锁造官路 有开销 需在渡路上 并发当时地 读取筛排 少送至些
2.原子指令官不需要
CAS原子指令的官路 无开销 渡路上的全部送至 都无所谓的
三、阻塞队列的解耦通信

1.直接交互
生产者消费者 直接交互地 在自己身上实现 锁同步与锁协调
// 直接交互
class DirectInteraction {
private String sharedData;
private boolean dataReady = false;
private final Object lock = new Object();
// 生产者
public void produce(String data) {
synchronized(lock) {
while(dataReady) { // 必须知道消费者的状态,等待消费者取走数据
try { lock.wait(); } catch (InterruptedException e) {}
}
sharedData = data;
dataReady = true; // 必须设置消费者需要的状态
lock.notify(); // 必须直接通知消费者
}
}
// 消费者
public String consume() {
synchronized(lock) {
while(!dataReady) { // 必须知道生产者的状态,等待生产者提供数据
try { lock.wait(); } catch (InterruptedException e) {}
}
String result = sharedData;
dataReady = false; // 必须设置生产者需要的状态
lock.notify(); // 必须直接通知生产者
return result;
}
}
}
1.1锁同步
在生产者消费者身上 加锁同步,生产消费 都是 整步地串行,处理了线程安全问题
1.2锁协调-乒乓交替协调
无缓冲区 是在生产者消费者身上 锁块里 设置检查 是否标记地 只能双方 乒乓交替执行 地锁协调
1.2.1效率
始终在阻塞一方,随机调度下 阻塞成了 必须双方交替地执行,执行效率低
2.间接交互
生产者与消费者之间 引入中间组件-队列 解耦通信
// 间接交互
class IndirectInteraction {
private BlockingQueue<String> queue = new ArrayBlockingQueue<>(10); // 已经在队列组件里 实现好了 生产消费的 锁同步与锁协调
// 生产者
public void produce(String data) {
try {
queue.put(data); // 生产者 只与共享的队列交互 调用队列里面的put方法即可,不关心消费者了
} catch (InterruptedException e) {}
}
// 消费者
public String consume() {
try {
return queue.take(); // 消费者 只与共享的队列交互 调用队列里面的take方法即可,不关心生产者了
} catch (InterruptedException e) { return null; }
}
}
2.1组件更换直接交互对象
内容互渗透、执行互拖欠 的紧密协调关系 转移,生产者与消费者 改成 与队列直接交互,彼此 间接交互 独立无联了
2.2组件分担功能实现 给封装共享使用
2.2.1实现所需的同步协调机制
封装在队列里实现的 put、take方法 已加锁同步 与用锁协调,生产者消费者 直接共享地 使用实现
2.2.2额外实现缓冲区管理
队列 能缓冲 生产消费不同伐协调 的待置数据,允许了 生产消费 以不同的速度运行
2.2.2.1锁协调-队列连续协调
有缓冲区后 是在队列组件上 锁块里 填取检查 队列是否满空地 可以一方连续执行 地锁协调
2.2.2.1.1平衡速度
在队列满空下 阻塞限制一方连续执行、另方可连续执行地 实况平衡 双方速度
2.2.2.1.2效率
只在队列满空时 才会使另方阻塞,随机调度下 双方少遇阻塞地 可以连续地执行,执行效率高![]()
![]()
更多推荐


所有评论(0)