我正在实现一个单生产者单用户队列,一个线程等待全局队列被另一个线程填充,如下所示:
while (queue.head == queue.tail);
当我编译程序将gcc -O0,它运作良好。但是当它用gcc -O1编译时,发生了死循环。然后我查看汇编代码,发现后一个版本只检查了一次(queue.head == queue.tail),如果不是,则跳转到死循环,再也不检查。
我也尝试将队列声明为volatile,但它不起作用。如何让gcc意识到队列在线程之间共享并停止优化呢?非常感谢。
P.S。
1在单线程程序中,可以像这样进行优化。但是在我的程序中,queue.tail可以被另一个线程修改。
2我的队列声明如下:
typedef struct {
struct my_data data[MAX_QUEUE_LEN];
int head;
int tail;
} my_queue_t;
volatile my_queue_t queue;
3我也尝试将head和tail(但不是整个结构)声明为volatile,它不起作用。但是在我声明队列后,head,tail都是volatile,它可以工作。那么应该将volatile声明为所有相关变量吗?
答案 0 :(得分:4)
我编译了以下代码:
struct my_data {
int x;
};
typedef struct {
struct my_data data[5];
int head;
int tail;
} my_queue_t;
volatile my_queue_t queue;
int main() {
while (queue.head == queue.tail);
}
with:
g++ -S -c -O1 th.cpp
(对于while循环)产生了以下输出:
movl $_queue+20, %edx
movl $_queue+24, %eax
L2:
movl (%edx), %ebx
movl (%eax), %ecx
cmpl %ecx, %ebx
je L2
头部和尾部装载的地方在循环内测试。你能发布一下你发出的汇编程序吗?
编辑:在struct声明中创建head和tail volatile,而不是声明struct instance volatile,导致代码相同。
答案 1 :(得分:3)
您是否尝试将头/尾声称为易失性?