2017-04-14 211 views
-1

代碼失敗:
[peterson_lock.h]我peterson_lock在這種情況下

#include <pthread.h> 

typedef struct { 
    volatile bool flag[2]; 
    volatile int 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; // Mark as A 
    lock.flag[id] = true; // Mark as B 
    asm volatile ("mfence" : : : "memory"); 
    while (lock.flag[1 - id] && lock.victim == id); 
} 

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

[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; 
} 

運行這個程序1000次,有時效果並非30000。但是,我切換AB,結果總是30000。但是這怎麼會發生?

[請忽略此行,才使這個問題可能是submitted.please忽略此行,才使這個問題可能是submitted.please忽略此行,才使這個問題可以提交。]

回答

0

該算法要求您交換A和B.換句話說,您的發佈代碼不是Peterson算法的正確實現。

讓我們看看出了什麼問題。

首先借此代碼:

void peterson_lock(peterson_lock_t &lock, int id) { 
    lock.victim = id; // Mark as A 
    lock.flag[id] = true; // Mark as B 
    asm volatile ("mfence" : : : "memory"); 
    while (lock.flag[1 - id] && lock.victim == id); 
} 

,並將其寫入按照處理的功能:

void peterson_lock_0(peterson_lock_t &lock) { 
    lock.victim = 0; 
    lock.flag[0] = true; 
    asm volatile ("mfence" : : : "memory"); 
    while (lock.flag[1] && lock.victim == 0); 
} 

void peterson_lock_1(peterson_lock_t &lock) { 
    lock.victim = 1; 
    lock.flag[1] = true; 
    asm volatile ("mfence" : : : "memory"); 
    while (lock.flag[0] && lock.victim == 1); 
} 

然後讓進程0執行的第一行,然後切換到處理1(在執行全功能),然後回到過程0.

peterson_lock_0:      peterson_lock_1: 
------------------------------------------------------- 
lock.victim = 0; 
             lock.victim = 1; 
             lock.flag[1] = true; 
             asm volatile ("mfence" : : : "memory"); 
             while (lock.flag[0] && lock.victim == 1); 
             // lock.flag[0] is false so 
             // the process enters critical 
             // section 
lock.flag[0] = true; 
asm volatile ("mfence" : : : "memory"); 
while (lock.flag[1] && lock.victim == 0); 
// lock.victim is 1 so 
// the process enters critical 
// section 

現在這兩個進程都處於關鍵部分。那很糟。

詳情https://en.wikipedia.org/wiki/Peterson%27s_algorithm

+0

謝謝,沒錯。 – Charles