2009-05-04 14 views
10

下面的代碼爲n和v生成隨機值。n沒有被正確保護就是隨機的,這並不奇怪。但是,它應該是最終應該是0.我的代碼有什麼問題嗎?或者任何人都可以爲我解釋這一點?謝謝。來自atomic.h的操作似乎是非原子的

我正在研究x86架構的四核服務器。 uname如下。

的Linux 2.6.9-22.ELsmp#1 SMP週一09月19日18時零零分54秒EDT 2005 x86_64的x86_64的x86_64的GNU/Linux的

#include <stdio.h> 
#include <pthread.h> 
#include <asm-x86_64/atomic.h> 

int n = 0; 
atomic_t v; 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 

#define LOOP 10000 

void* foo(void *p) 
{ 
    int i = 0; 
    for(i = 0; i < LOOP; i++) { 
//  pthread_mutex_lock(&mutex); 
     ++n; 
     --n; 
     atomic_inc(&v); 
     atomic_dec(&v); 
//  pthread_mutex_unlock(&mutex); 
    } 

    return NULL; 
} 

#define COUNT 50 

int main(int argc, char **argv) 
{ 
    int i; 
    pthread_t pids[COUNT]; 
    pthread_attr_t attr; 
    pthread_attr_init(&attr); 
    atomic_set(&v, 0); 

    for(i = 0; i < COUNT; i++) { 
     pthread_create(&pids[i], &attr, foo, NULL); 
    } 

    for(i = 0; i < COUNT; i++) { 
     pthread_join(pids[i], NULL); 
    } 

    printf("%d\n", n); 
    printf("%d\n", v); 
    return 0; 
} 
+5

我沒有答案,但我想說:感謝您提供完整的工作源代碼的清晰措辭,明確的問題。我希望每個人都能這樣做! – RichieHindle 2009-05-04 08:38:09

回答

3

我們可以看看代碼的彙編程序輸出(gcc -E,我認爲)。即使認爲uname表示它具有SMP意識,但這並不一定意味着它是用CONFIG_SMP編譯的。

沒有這一點,彙編代碼輸出沒有lock前綴,你可以發現你的核心互相干擾。

但是我會使用pthread函數,因爲它們可以跨多個平臺移植。

4

This old post意味着

  • 這不是很明顯你應該在用戶空間程序中包含這個內核頭文件
  • 已知無法爲用戶空間程序提供原子性。

所以......也許這就是你看到的問題的原因?

+0

感謝您的信息。我只是想知道爲什麼Linux內核不會將這些有用的原語暴露給用戶級程序。它們比pthread_mutex方法更輕量且更高效。 – Hank 2009-05-04 09:16:57

+0

@hank,好吧,內核實際上是這樣做的。它的glibc令人困惑。 – 2009-05-04 10:36:25

6

您應該使用gcc內置代替(請參閱this)此工作正常,也適用於icc。

int a; 
__sync_fetch_and_add(&a, 1); // atomic a++ 

請注意,當您不鎖定地修改變量時,應該知道緩存一致性問題。

0

Linux內核atomic.h不能從userland使用,從來沒有。在x86上,它可能有效,因爲x86是非常適合同步的體系結構,但在某些平臺上,它很大程度上依賴於能夠執行特權操作(舊手臂)或至少能夠禁用搶佔(舊手臂和sparc至少),這是不是在用戶國!