环形队列

基础环形队列需要保证任意时刻至多只有一个生产者和一个消费者。多线程多生产者带来的问题:

P1、P2 同时向队列写入数据,同时读到 tail 为 0,然后 P1 执行写入,P2 再执行写入,最终两次写入都成功,但是 P1 的内容被 P2 覆盖。

解决:

#数据结构 留空法: 在循环队列中,求队列的长度也不仅仅是rear与front相减这么简单,因为,rear的值有可能比front小,这样相减结果是负值,显然不对。在求循环队列的长度时,都是用rear加上队列容量,减去front的值后,再对容量取模:(rear + MAXSIZE - front) % MAXSIZE。留空法队满时头尾指针不相等,其他队满时头尾指针相等的方法,无法使用上述公式计算容量。

优点

  • 简单、粗暴;

缺点

缓冲区(固定地址段)长度设为2的幂,是为了省略镜像指示位(用于判断缓冲区是否已满):如果读写指针的值相等,则缓冲区为空;如果读写指针相差n(缓冲区大小),则缓冲区为满

我的疑问是:为什么缓冲区长度不是 2 的幂,就需要镜像指示位?

linux中环形缓冲区(ring buffer)的实现,其实是对2.2.3节介绍的镜像指示位策略的扩展,读指针和写指针区间范围不再局限在镜像区间[0,2n−1],而是整个unsigned int大小的空间,对于32位机器,读指针和写指针的区间范围是,[0,232−1];

  • 进行扩展后,还能维持如下的关系,是因为缓冲区大小n会被扩展为2的幂,那么232肯定是n扩展后的整数倍,所以还是能够满足如下关系;

读索引读指针缓冲区长度读索引=读指针&(缓冲区长度−1)写索引写指针缓冲区长度写索引=写指针&(缓冲区长度−1)

异或运算的性质和结果与 <code>a</code> 和 <code>b</code> 之间的关系: #

  1. 按位比较

    • 每一位上的异或结果由 a 和 b 对应位的值决定。对于每一位,若 a 和 b 相同,则该位的结果为 0;若不同,则该位的结果为 1。
  2. 无进位加法

    • 异或可以看作是对两个数按位加法的“无进位”版本。换句话说,它相当于在每一位上执行加法运算,但忽略了进位。例如,1 + 1 = 10,在普通加法中进位为 1,而在异或中,进位被忽略,只保留最低位的 0。
  3. 交换律和结合律

    • 异或满足交换律和结合律,即:
      • 交换律a ^ b = b ^ a
      • 结合律(a ^ b) ^ c = a ^ (b ^ c)
  4. 自反性

    • a ^ a = 0:任何数与自身异或的结果是 0。这是因为每个位上相同的值异或会得到 0。
  5. 与 0 异或

    • a ^ 0 = a:任何数与 0 异或的结果是它本身。

最高有效位(英语:Most Significant Bitmsb),是指一个n位二进制数字中的n-1位,具有最高的权值2n−1

{\displaystyle 2^{n-1}}
。与之相反的称之为最低有效位。在大端序中,msb即指最左端的位。

最低有效位(英语:Least Significant Bitlsb)是指一个二进制数字中的第0位(即最低位),权值为2^0,可以用它来检测数的奇偶性。与之相反的称之为最高有效位。在大端序中,lsb指最右边的位。

GLIC 的GLIST的双向链表使用方法

通用 C 链表