并行下的「生产者-消费者」

664 阅读2分钟

这是我参与8月更文挑战的第30天,活动详情查看:8月更文挑战

生产者消费者的晋升

  • 这一节我们会使用Disruptor框架来实现
  • 首先还是实体类,代表数据对象

图片.png

  • 来看消费者,是实现了WorkHandler接口
    • 主要进行数据的读取和处理,被封装在了Disruptor框架中

图片.png

  • 我们还需要创建一个AData的工厂类,在框架初始化的时候,会构造出所有的缓冲区中的对象实例
/**
 * @Author: xiaoff
 * @Date: 2021/8/26 08:52
 */
public class ADataFactory implements EventFactory<AData>{
    
    public AData new instance() {
        return new AData();
    }
}
  • 来看生产者,其中的RingBuffer就是一个环形的缓冲区
    • 主要将产生的数据放入缓冲区中
    • ByteBuffer就是用来装载或者包装任何一种数据类型
    • 本文中用到的是long类型
    • next是得到下一个可用的序列号

/**
 * @Author: xiaoff
 * @Date: 2021/8/26 23:54
 */
public class Producer {

    private  final RingBuffer<AData> ringBuffer;

    public Producer(RingBuffer<AData> ringBuffer) {
        this.ringBuffer =ringBuffer;
    }

    // 用来接收ByteBuffer对象
    public void PushData(ByteBuffer bf) {
        // 拿到下一个数据/任务的序列号
        long next = ringBuffer.next();
        AData data = ringBuffer.get(next);
        // 放入数据
        data.setValue(bf.getLong(0));
        // 放入环形缓冲区
        ringBuffer.publish(next);
    }
}

伪共享问题

  • 为了提高CPU的速度,往往会提到高速缓存Cache
    • Cache读写数据的最小单位是缓存行
    • 它是从主存复制到缓存的最小单位
    • 一般是32字节~128字节
  • 当两个变量存在一个缓存行的时候
    • 多线程访问的时候,可能会彼此影响性能
    1. 假设X Y在同一个缓存行
    2. CPU1更新了X,CPU2上的缓存行就会失效
    3. 如果反过来也是如此
  • 为了避免以上的情况,可以在变量X的前后恐案件先占一定的位置
    • 当内存被读入缓存的时候,变量X就会有效
    • 不会导致多个线程修改缓存行中的不同变量导致变量全体失效