1

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 !!!!

4

1 に答える 1