这里说的环形队列是一种内存通讯机制,本身这个机制和语言没有什么关系,不过上篇提到了volatile语法和acquire/release语义,就以这个机制做一个例子,C语言实现。这方面的内容涉及到一些现有的语言实现的东西
环形队列的数据结构是一个数组,简单起见我们认为通讯内容就是一个个int,则定义一个int数组和头尾索引:
然后是读写:
假如有多个线程读写队列,则一般需要锁来实现同步,但是做一点点约束和修改,就能实现无锁:
1 队列只能单读单写
2 共享的数据用volatile修饰
可以就上面的代码简单分析下,read操作只会读写head,读tail和queue,反之write操作读写tail,读head,写queue,而head和tail都是正向增长的。这里的关键在于,head和tail使用int,它们的读写用一条机器指令即可完成,是原子的,在这个前提下,上述两个
环形队列的数据结构是一个数组,简单起见我们认为通讯内容就是一个个int,则定义一个int数组和头尾索引:
int queue[SIZE];
int head;
int tail;
方便起见可以约定:head表示队列首元素的索引,tail表示队列尾元素后面的空位的索引,队列中最多可容纳SIZE-1个元素,因为这样可以head==tail表示队列空,head==(tail+1)%SIZE表示队列满,如果能容纳SIZE个元素,就不能区分这两种情况了
然后是读写:
ErrorType read(int *v)
{
if (head == tail)
{
return EMPTY;
}
*v = queue[head];
head = (head + 1) % SIZE;
return SUCCESS;
}
ErrorType write(const int *v)
{
if (head == (tail + 1) % SIZE)
{
return FULL;
}
queue[tail] = *v;
tail = (tail + 1) % SIZE;
return SUCCESS;
}
假如有多个线程读写队列,则一般需要锁来实现同步,但是做一点点约束和修改,就能实现无锁:
1 队列只能单读单写
2 共享的数据用volatile修饰
可以就上面的代码简单分析下,read操作只会读写head,读tail和queue,反之write操作读写tail,读head,写queue,而head和tail都是正向增长的。这里的关键在于,head和tail使用int,它们的读写用一条机器指令即可完成,是原子的,在这个前提下,上述两个