【发布时间】:2017-09-20 03:00:26
【问题描述】:
我试图通过一个示例来了解volatile 的行为和C 中的编译器优化。
为此,我提到了:
以上所有帖子都至少有一个与信号处理程序相关的答案,因此为此,我编写了一个简单的代码来实际实现和观察 Linux 中的行为,只是为了理解。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
int counter = 0;
void *thread0_func(void *arg)
{
printf("Thread 0\n");
while(1)
{
}
return NULL;
}
void *thread1_func(void *arg)
{
printf("Thread 1\n");
while(counter == 0)
{
printf("Counter: %d\n", counter);
usleep(90000);
}
return NULL;
}
void action_handler(int sig_no)
{
printf("SigINT Generated: %d\n",counter);
counter += 1;
}
int main(int argc, char **argv)
{
pthread_t thread_id[2];
struct sigaction sa;
sa.sa_handler = action_handler;
if(sigaction(SIGINT, &sa, NULL))
perror("Cannot Install Sig handler");
if(pthread_create(&thread_id[0], NULL, thread0_func, NULL))
{
perror("Error Creating Thread 0");
}
if(pthread_create(&thread_id[1], NULL, thread1_func, NULL))
{
perror("Error Creating Thread 0");
}
else
{
}
while(1)
{
if(counter >= 5)
{
printf("Value of Counter is more than five\n");
}
usleep(90000);
}
return (0);
}
此代码仅供学习和理解。
我尝试使用以下代码编译代码:gcc -O3 main.c -o main -pthread
但是编译器没有作用于全局变量counter,也没有对其进行优化。
我期待*thread1_func 永远循环执行,而if (counter >= 5) 永远不会是真的。
我在这里错过了什么?
GCC 版本:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
【问题讨论】:
-
如果
action_handler被实际执行,程序有未定义的行为。 -
为什么会这样?
-
您正在修改
counter,同时从另一个线程访问它。这是不允许的。 -
那么,解决办法是声明它为volatile?
-
如果你没有线程,你可以声明它
volatile sig_atomic_t。对于线程,它不能保证工作,您需要一个实际的同步机制(互斥锁、信号量或类似的)。不过,我不确定您是否可以从信号处理程序中使用它们。
标签: c linux gcc optimization volatile