gpt4 book ai didi

c++ - c中的内存位置和数据竞争

转载 作者:太空宇宙 更新时间:2023-11-04 02:06:50 25 4
gpt4 key购买 nike

http://www.stroustrup.com/C++11FAQ.html#memory-model

页面描述:

// thread 1:
char c;
c = 1;
int x = c;

// thread 2:
char b;
b = 1;
int y = b;

.....

然而,大多数现代处理器无法读取或写入单个字符,它必须读取或写入整个单词,因此对 c 的赋值实际上是``读取包含 c 的单词,替换 c 部分,然后写入这个词又回来了。''由于对 b 的赋值是相似的,所以即使线程不(根据它们的源文本)共享数据,两个线程也有很多机会互相破坏!

我有一个结构:

struct data_
{
volatile char c ;
volatile char b ;
} __attribute__(( aligned(2) ));
typedef struct data_ data ;

和全局变量:

data dx ; 
int x,y ;

线程 1:

    dx.c = 1 ;
x = dx.c ;

线程 2:

    dx.b = 1 ;
y = dx.b ;

在 gcc 4.4.6 编译,并运行 1,000,000 次, 看起来我没有得到任何不是 (x==1 && y==1) !!!!

struct data_
{
volatile char c ;
volatile char b ;
} __attribute__(( aligned(2) ));

我故意将 char c 和 char b 放在一个 aligned(2) 结构中,这样它们都属于同样的话,根据网页描述,我可能有机会得到结果不是 (x==1 && y==1) ,事实是运行测试 1,000,000 次,都得到 (x==1 && y==1) ,那是因为 gcc 做了什么把戏吗?还是我错过了什么?

编辑:

线程 1:

int ilocal ;
while(1)
{
sem_wait(sem1) ;
dx.c = 1 ;
x = dx.c ;
ilocal = __sync_add_and_fetch(&icnt,1) ;
if(ilocal == 2)
sem_post(sem3) ;
++icnt1 ;
}

线程 2:

int ilocal ;
while(1)
{
sem_wait(sem2) ;
dx.b = 1 ;
y = dx.b ;
ilocal = __sync_add_and_fetch(&icnt,1) ;
if(ilocal == 2)
sem_post(sem3) ;
++icnt2 ;
}

主要内容:

int idx,iflag1=0,iflag2=0 ;
for(idx=0;idx<1000000;idx++)
{
icnt = 0 ; dx.c=0 ; dx.b=0 ;
sem_post(sem1) ;
sem_post(sem2) ;
sem_wait(sem3) ;
if( ! ((x==1)&&(y==1)) )
{
printf("result that (x==%d && y==%d) \n",x,y) ;
++iflag1 ;
}else{
++iflag2 ;
}
} //while
printf("iflag1=(%d),iflag2=(%d)\n",iflag1,iflag2) ;
printf("icnt1=(%d),icnt2=(%d) \n",icnt1,icnt2) ;

gcc memorylocate.c -lpthread -o memorylocate.exe

sizeof data=(64) //source already change to __attribute__(( aligned(64) )
iflag1=(0),iflag2=(1000000)
icnt1=(1000000),icnt2=(1000000)

编辑2:

我想我终于弄明白了!!

struct { char c ; char b ;}

c 和 b 会是不同的内存位置,这样他们就可以线程安全访问了!!cpu 可以原子地访问单字节字符!!!!!

我将代码更改为:

struct data_
{
unsigned char c:4 ;
unsigned char b:4 ;
} ;

主要是:

for(idx=0;idx<1000000;idx++)
{
icnt = 0 ; dx.c=0 ; dx.b=0 ;
sem_post(sem1) ;
sem_post(sem2) ;
sem_wait(sem3) ;
if( ! ((dx.c==1)&&(dx.b==1)) )
{
printf("result that (x==%d && y==%d) \n",x,y) ;
++iflag1 ;
}else{
++iflag2 ;
}
} //while

我观察到有些结果不是 (dx.c==1)&&(dx.b==1) !!这是因为在这种情况下 dx.c 和 dx.b 位于相同的内存位置!!!!

所以我犯了一个错误,最重要的是决定内存位置,struct {char c; char b;} , char c 和char b 在不同的内存位置,测试结果是正确的!!!!

最佳答案

参见 C++ 标准中的 1.7 [intro.memory] ​​p3:

A memory location is either an object of scalar type or a maximal sequence of adjacent bit-fields all having non-zero width. [ Note: ... ] Two or more threads of execution (1.10) can update and access separate memory locations without interfering with each other.

因此,符合标准的编译器只需确保可以在不影响其他内存位置的情况下更新 char。

关于c++ - c中的内存位置和数据竞争,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19761707/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com