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;
.....
しかし、最新のプロセッサのほとんどは、1 文字の読み書きができず、単語全体を読み書きする必要があるため、c への代入は、実際には「c を含む単語を読み取り、c の部分を置き換え、単語を書き戻す」ことになります。 ' b への代入は似ているため、2 つのスレッドが (ソース テキストによると) データを共有していなくても、2 つのスレッドが互いに破壊する機会はたくさんあります!
私は構造体を持っています:
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)構造体に入れて、両方が同じ単語に属するようにしました。Webページの説明によると、(x==1 && y=ではない結果が得られる可能性があります。 =1) 、実際には、テストを 1,000,000 回実行し、すべて get (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 は 1 バイト char にアトミックにアクセスできます!!!!!
コードを次のように変更します。
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 が同じメモリ位置にあるためです!!!!
So I make a mistake , the most important thing to decide is memory location , struct {char c; char b;} , char c and char b is in different memory location , the test result is correct !!!!