0

我有以下代码:

#include <stdio.h>
#include <pthread.h>
#define THREAD_CNT 10
#define ITER 100
#define PRINT 1

int lock;
unsigned long long int counter;

void spin_lock(int *p) {
    while(!__sync_bool_compare_and_swap(p, 0, 1));
}

void spin_unlock(int volatile *p) {
    asm volatile ("");
    *p = 0;
}

void *exerciser(void *arg) {
    unsigned long long int i;
    int id = (int)arg;
    for(i = 0; i < ITER; i++) {
        spin_lock(&lock);
        counter = counter + 1;
        if(PRINT) {
            printf("%d: Incrementing counter: %llu -> %llu\n", id, counter-1, counter);
        }
        spin_unlock(&lock);
    }
    pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
    pthread_t thread[THREAD_CNT];
    counter = 0;
    int i;
    for(i = 0; i < THREAD_CNT; i++) {
        pthread_create(&thread[i], NULL, exerciser, (void *) i);
    }
    for(i = 0; i < THREAD_CNT; i++) {
        pthread_join(thread[i], NULL);
    }
    printf("Sum: %llu\n", counter);
    printf("Main: Program completed. Exiting.\n");
    pthread_exit(NULL);
}

PRINT定义为 1 时,我最后得到正确的计数器值:

7: Incrementing counter: 996 -> 997
7: Incrementing counter: 997 -> 998
7: Incrementing counter: 998 -> 999
7: Incrementing counter: 999 -> 1000
Sum: 1000
Main: Program completed. Exiting.

如果我设为PRINT0,我会得到以下结果(多次运行):

$ ./a.out
Sum: 991
Main: Program completed. Exiting.
$ ./a.out 
Sum: 1000
Main: Program completed. Exiting.
$ ./a.out 
Sum: 962
Main: Program completed. Exiting.
$ ./a.out 
Sum: 938
Main: Program completed. Exiting.

关于发生了什么的任何见解?为什么当我启用打印语句时,我的结果(始终)正确,但我禁用它并且我的计数器没有达到目标值?我已经使用了很多 pthread,但在直接使用自旋锁方面并不是很有经验。

任何帮助或反馈表示赞赏。

4

1 回答 1

1

您的锁定方法实际上并没有做任何事情:由于参数是按值传递的,因此您实际上并没有测试/设置全局锁定的值。您只是在更改函数获得的变量副本的值。

相反,如果您的 spin_lock/spin_unlock 方法使用指向整数(即&lock)的指针来使用,那么您的代码应该可以工作。

您的承重 printf 可能会导致一些意外的同步,因为 printf 应该是线程安全的。

于 2012-06-24T10:26:44.060 回答