目录

一、线程方法(三):wait-notify锁自定协调

1.实现规格

2.线程欠量

3.线程塞等

4.欠等互斥

二、线程安全(一).3:条件产生渡送执行

1.临执行无缝能改路官口检查

2.加锁多铺一路上的无缝能改路

三、阻塞队列的解耦通信

1.直接交互

1.1锁同步

1.2锁协调-乒乓交替协调

1.2.1效率

2.间接交互

2.1组件更换直接交互对象

2.2组件分担功能实现 给封装共享使用

2.2.1实现所需的同步协调机制

2.2.2额外实现缓冲区管理

2.2.2.1锁协调-队列连续协调

2.2.2.1.1平衡速度

2.2.2.1.2效率


一、线程方法(三):wait-notify锁自定协调

知识连接:

线程方法(一):中断和等待

线程方法(二):wait/notify等待通知机制

抢锁块里进行的 此线程等条件 厌锁欠执行、另线程归条件 醒锁还执行 的锁协调模式

1.实现规格

锁往小里面加,锁协调 占最小的行 就可实现


2.线程欠量

每个线程 最多只能 在欠着一个执行,同方线程 指 同欠等条件方向的多个线程


3.线程塞等

线程 入阻塞地 等待条件,避免了 忙等待 浪费cpu的资源


4.欠等互斥

欠等条件互斥的线程 始终至少有另方 可条件地执行

但可能会因为 唤醒没通知到 它的对立条件可执行线程 而最终 一方条件不符 厌锁入眠 另方条件满足 但缺唤醒 地都在 待唤醒 阻塞中


二、线程安全(一).3:条件产生渡送执行

知识连接:

线程安全(一).1:不安全原因和措施

线程安全(一).2:指令全排序

线程安全(一).4:写块串行保安全

线程安全(一).5:总

正确条件 从产生 能渡送到 执行处 的保障实现

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效率

只在队列满空时 才会使另方阻塞,随机调度下 双方少遇阻塞地 可以连续地执行,执行效率高

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐