2017-04-10 5 views
-2

私は単純にPeterson Lock Algorithmを実装しますが、正しく機能しません。私は間違った方法でメモリバリアを使用しますか?

#include <pthread.h> 

typedef struct { 
    volatile bool flag[2]; 
    volatile bool victim; 
} peterson_lock_t; 

void peterson_lock_init(peterson_lock_t &lock) { 
    lock.flag[0] = lock.flag[1] = false; 
    lock.victim = 0; 
} 

void peterson_lock(peterson_lock_t &lock, int id) { 
    lock.victim = id; 
    lock.flag[id] = true; 
    __asm__ __volatile__("" : : : "memory"); 
    while (lock.flag[1 - id] == false && lock.victim != id); 
} 

void peterson_unlock(peterson_lock_t &lock, int id) { 
    lock.flag[id] = false; 
} 

このコードで何が問題になっています:
ここ は、コードのですか?

main.cppに:

#include <stdio.h> 
#include "peterson_lock.h" 

peterson_lock_t lock; 
int count = 0; 

void *routine0(void *arg) { 
    int *cnt = (int *)arg; 
    for (int i = 0; i < *cnt; ++i) { 
     peterson_lock(lock, 0); 
     ++count; 
     peterson_unlock(lock, 0); 
    } 

    return NULL; 
} 

void *routine1(void *arg) { 
    int *cnt = (int *)arg; 
    for (int i = 0; i < *cnt; ++i) { 
     peterson_lock(lock, 1); 
     ++count; 
     peterson_unlock(lock, 1); 
    } 
} 

int main(int argc, char **argv) { 
    peterson_lock_init(lock); 
    pthread_t thread0, thread1; 
    int count0 = 10000; 
    int count1 = 20000; 
    pthread_create(&thread0, NULL, routine0, (void *)&count0); 
    pthread_create(&thread1, NULL, routine1, (void *)&count1); 

    pthread_join(thread0, NULL); 
    pthread_join(thread1, NULL); 

    printf("Expected: %d\n", (count0 + count1)); 
    printf("Reality : %d\n", count); 

    return 0; 
} 

、結果は適切ではない。期待

:30000
現実:24304

予想:30000
現実:24316

OS:
LinuxのIP-172-31-43-244 3.14.35-28.38.amzn1.x86_64#1 SMP水3月11日午前22時50分37秒UTC 2015 x86_64のx86_64でのx86_64のGNU/Linuxの

+2

どのように誤って動作していますか? –

+0

@Colin__s私はこれをテストし、結果は間違っています。私は 'main'のコードを更新します。 – Charles

+2

'volatile'はメモリバリアとして機能しません。 'std :: atomic'や他のメモリフェンスを使います。 _ "...これは、揮発性オブジェクトをシグナルハンドラとの通信に適していますが、別の実行スレッドでは使用できません"ソース:http://en.cppreference.com/w/cpp/language/cv –

答えて

0

状態も改善する必要がつつ:

一方(lock.flag [1 - ID] ==真& & lock.victim == ID) 続けます。 他のスレッドがロックされ、あなたが犠牲になるまでビジー状態になります。

Peterson Lock

関連する問題