当前位置: 技术问答>linux和unix
问一个关于临界区同步的问题
来源: 互联网 发布时间:2016-07-20
本文导语: 下面是UNIX系统编程里的一道程序 #include #include #include #include static volatile sig_atomic_t doneflag = 0; static void setdoneflag(int signo) { doneflag = 1; } int main(void) { struct sigaction set; int count = 0; dou...
下面是UNIX系统编程里的一道程序
#include
#include
#include
#include
static volatile sig_atomic_t doneflag = 0;
static void setdoneflag(int signo)
{
doneflag = 1;
}
int main(void)
{
struct sigaction set;
int count = 0;
double sum = 0;
double x;
act.sa_handleer = setdoneflag;
act.sa_flags = 0;
if((sigemptyset(&act.sa_mask) == -1)||(sigaction(SIGINT,&act,NULL)==-1))
{
perror("Failed to set sigint handle");
return 1;
}
while(!doneflag)
{
x = (rand()+0.5)/(RAND_MAX+1.0);
sum += sin(x);
count++;
printf("count is %d and average is %fn",count,sum/count);
}
printf("program terminating...n");
if(count == 0)
printf("no values calculated yetn");
else
printf("count is %d and average is %fn",count,sum/count);
return 0;
}
里面说因为可能在main函数检查doneflag的时候,信号处理函数对这个变量进行更改,所以doneflag设置成原子变量。
我想问一下,如果不设置doneflag为原子变量的话,在检查doneflag的时候对变量进行更改会发生什么情况?
我不设置为原子变量会有什么影响?
#include
#include
#include
#include
static volatile sig_atomic_t doneflag = 0;
static void setdoneflag(int signo)
{
doneflag = 1;
}
int main(void)
{
struct sigaction set;
int count = 0;
double sum = 0;
double x;
act.sa_handleer = setdoneflag;
act.sa_flags = 0;
if((sigemptyset(&act.sa_mask) == -1)||(sigaction(SIGINT,&act,NULL)==-1))
{
perror("Failed to set sigint handle");
return 1;
}
while(!doneflag)
{
x = (rand()+0.5)/(RAND_MAX+1.0);
sum += sin(x);
count++;
printf("count is %d and average is %fn",count,sum/count);
}
printf("program terminating...n");
if(count == 0)
printf("no values calculated yetn");
else
printf("count is %d and average is %fn",count,sum/count);
return 0;
}
里面说因为可能在main函数检查doneflag的时候,信号处理函数对这个变量进行更改,所以doneflag设置成原子变量。
我想问一下,如果不设置doneflag为原子变量的话,在检查doneflag的时候对变量进行更改会发生什么情况?
我不设置为原子变量会有什么影响?
|
1.对整数进行判断(while(!doneflag))的话,分两步,1.从内存中去数据到寄存器,2.放入运算器,返回结果
如果在1和2之间发生中断,doneflag=1。然后中断返回,while条件仍然为假(其实变量已经为1,条件应该为真)
为了保证上述情况不发生,因此要将doneflag定义为原子类型,使之第一和第二之间不能发生中断。
至于3楼的那段应该是来自glic的手册中的。意思应该在gnu的编译器,整数被当成原子类型处理
但是不包含其他操作系统中,其他编译器怎么处理。因此最好自己手工定义为原子类型。
如果在1和2之间发生中断,doneflag=1。然后中断返回,while条件仍然为假(其实变量已经为1,条件应该为真)
为了保证上述情况不发生,因此要将doneflag定义为原子类型,使之第一和第二之间不能发生中断。
至于3楼的那段应该是来自glic的手册中的。意思应该在gnu的编译器,整数被当成原子类型处理
但是不包含其他操作系统中,其他编译器怎么处理。因此最好自己手工定义为原子类型。
|
To avoid uncertainty about interrupting access to a variable, you can use a particular data
type for which access is always atomic: sig_atomic_t. Reading and writing this data type
is guaranteed to happen in a single instruction, so there's no way for a handler to run in
the middle" of an access.
The type sig_atomic_t is always an integer data type, but which one it is, and how
many bits it contains, may vary from machine to machine.
sig_atomic_t [Data Type]
This is an integer data type. Objects of this type are always accessed atomically.
In practice, you can assume that int is atomic. You can also assume that pointer
types are atomic; that is very convenient. Both of these assumptions are true on all
type for which access is always atomic: sig_atomic_t. Reading and writing this data type
is guaranteed to happen in a single instruction, so there's no way for a handler to run in
the middle" of an access.
The type sig_atomic_t is always an integer data type, but which one it is, and how
many bits it contains, may vary from machine to machine.
sig_atomic_t [Data Type]
This is an integer data type. Objects of this type are always accessed atomically.
In practice, you can assume that int is atomic. You can also assume that pointer
types are atomic; that is very convenient. Both of these assumptions are true on all