linux -多线程
竞态条件
竞态条件是指多个执行流访问同一个资源的情况下,会对程序产生一个二义性的结果。
- 重入: 多个执行流可以访问到同一个资源
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int count = 0;
void sigcallback(int signo)
{
// count++;
printf("i recv sig no is [%d],and count = [%d]\n",signo,count);
}
int main()
{
signal(2,sigcallback);
while(count < 20)
{
count++;
printf("i am main thread : [%d]\n",count);
sleep(1);
}
}
- 可重入: 多个执行流访问同一个资源,但是不会对程序的结果产生影响
- 不可重入:多个执行流访问同一资源,会产生一个二义性的结果(与我们所想的结果不一样)
volatile关键字
volatile关键字的作用就是让变量保持内存可见性
程序中的数据的流向,一般是,cpu -> 寄存器 -> 缓存 -> 内存 -> 磁盘
这个程序,我们虽然改掉了全局变量 g_val 的值,但是主函数中的 g_val 其实还是1,因为主函数中没有进行调用,他g_val的值一直都是寄存器中的值,我们只是在回调函数中改掉了内存中的值,寄存器中的值还没有改变,所有程序才会一直陷入死循环中。
为了解决这一种情况,我们可以在类型前加上volatile关键字,从而用volatile声明,该关键字的作用是防止优化编译器把变量从内存装入CPU寄存器中。如果变量被装入寄存器,那么两个线程有可能一个使用内存中的变量,一个使用寄存器中的变量,这会造成程序的错误执行。volatile的意思是让编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值,从而摒弃编译器优化选项。
编译器优化选项有 -O0, -O1,-O2,-O3,后面的总比前面的优化程度高。
makefile
threadexit:threadexit.c
gcc -O2 $^ -o $@ -g
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
volatile int g_val = 1;
void sigcallback(int sigo)
{
g_val = 0;
printf("signal [%d],[%d]\n",sigo,g_val);
}
int main()
{
signal(2,sigcallback);
while(g_val)
{
}
return 0;<