美文网首页
无锁环形缓冲区

无锁环形缓冲区

作者: yuansip | 来源:发表于2016-11-14 18:29 被阅读0次

对于单生产者-单消费者的情况,可以实现无锁环形缓冲区,常见的实现如下:

public class RingBuffer {
    private int mHead;
    private int mTail;
    private char[] mBuffer;
    public RingBuffer(int size) {
        if (size < 2) {
            throw new Exception("size should be greater than 2");
        }
        mBuffer = new char[size];
        mHead = 0;
        mTail = 0;
    }
    public int length() {
        return (mTail + mBuffer.length - mHead) % mBuffer.length;
    }
    public boolean isEmpty() {
        return mHead == mTail;
    }
    public boolean isFull() {
        return mHead == ((mTail + 1) % mBuffer.length);
    }
    public char read() {
        if (isEmpty()) {
            throw new Exception("buffer is already empty");
        }
        char ch = mBuffer[mHead];
        mHead = (mHead + 1) % mBuffer.length;
        return ch;
    }
    public void write(char ch) {
        if (isFull()) {
            throw new Exception("buffer is already full");
        }
        mBuffer[mTail] = ch;
        mTail = (mTail + 1) % mBuffer.length;
    }
}

mHead表明下一个可读取的位置,mTail表明下一个可写入的位置,head和tail重合时,表明buffer是空的;为了区分empty和full,强制要求tail和head之间至少要空一个元素,也就是说对于size为N的数组实现的环形buffer,最多只能存放N - 1个元素。如果不做这样的强制要求,则无法区分empty和full。因此,数组的size要大于2才有效。read和write函数各自只修改了head和tail, 所以即使运行在不同的线程,也能保证数据的一致性。

对于size为N的数组实现的环形buffer,如果想实现最多可以存放N个元素,则必须引入length变量,而且无法做到lock-free。也就是说,只借助head和tail, 无法区分empty和full, 所以要借助empty和full时head和tail的间隔不同来帮忙区分。

public class RingBuffer {
    private int mHead;
    private int mTail;
        private int mLength;
    private char[] mBuffer;
    public RingBuffer(int size) {
        if (size < 1) {
            throw new Exception("size should be greater than 0");
        }
        mBuffer = new char[size];
        mHead = 0;
        mTail = 0;
    }
    public int length() {
        return mLength;
    }
    public boolean isEmpty() {
        return length() == 0;
    }
    public boolean isFull() {
        return length() == mBuffer.length;
    }
    public char read() {
        if (isEmpty()) {
            throw new Exception("buffer is already empty");
        }
        char ch = mBuffer[mHead];
        mHead = (mHead + 1) % mBuffer.length;
                mLength--;
        return ch;
    }
    public void write(char ch) {
        if (isFull()) {
            throw new Exception("buffer is already full");
        }
        mBuffer[mTail] = ch;
                mTail = (mTail + 1) % mBuffer.length;
        mLength++;
    }
}

参考阅读

深入浅出网络模型
透过linux内核看无锁编程

相关文章

  • 无锁环形缓冲区

    对于单生产者-单消费者的情况,可以实现无锁环形缓冲区,常见的实现如下: mHead表明下一个可读取的位置,mTai...

  • 【RTOS训练营】环形缓冲区、AT指令、预习安排和晚课提问

    一、环形缓冲区 在上一次课中,只讲了UART的硬件协议,没有讲环形缓冲区。 本节课就讲解环形缓冲区。 环形缓冲区它...

  • 循环缓冲区

    参考 圆形缓冲区(循环buffer)实现35.Linux-分析并制作环形缓冲区 环形缓冲区构成一般的,圆形缓冲区需...

  • 笨办法学C 练习44:环形缓冲区

    练习44:环形缓冲区 原文:Exercise 44: Ring Buffer 译者:飞龙 环形缓冲区在处理异步IO...

  • C语言实现环形缓冲区

    环形缓冲区 环形缓冲区的特性1、先进新出2、当缓冲区被使用完,且又有新的数据需要存储时,丢掉历史最久的数据,保存最...

  • 无锁环形队列

    并发编程中,经常会遇到资源竞争问题,而保持竞争资源的正确使用,可以通过锁的方式,但synchronized blo...

  • 环形缓冲区

    下面引用维基百科,来学习环形缓冲区。 环形缓冲器 圆形缓冲区(circular buffer),也称作圆形队列(c...

  • 环形缓冲区的工作原理

    环形缓冲区的工作原理 环形缓冲区的工作原理,就是一个环形数组大小默认100M,初始时将环形数组一分为二,从一处开始...

  • 循环缓冲区(RingBuffer)

    一、简介 1、循环缓冲区的实现原理 环形缓冲区通常有一个读指针和一个写指针。读指针指向环形缓冲区中可读的数据,写指...

  • 数据结构-环形缓冲区-- Circular Buffer(Rin

    环形缓冲区-- Circular Buffer(Ring Buffer)C/C++ 可用 什么是循环缓冲区 循环缓...

网友评论

      本文标题:无锁环形缓冲区

      本文链接:https://www.haomeiwen.com/subject/qkohpttx.html