我有以下代码:
#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.
如果我PRINT
0,我会得到以下(多次运行):
$ ./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.
有关正在发生的事情的任何见解?为什么当我启用print语句时,我的结果是(一致地)正确,但我禁用它并且我的计数器没有达到目标值?我已经使用过pthread了很多但没有直接使用自旋锁的经验。
感谢任何帮助或反馈。
答案 0 :(得分:1)
你的锁方法实际上并没有做任何事情:因为参数是按值传递的,所以你实际上并没有测试/设置你的锁全局值。您只是更改函数获得的变量副本的值。
如果您的spin_lock / spin_unlock方法使用指向整数(即&lock
)的指针来使用,那么您的代码应该可以工作。
你的承载printf可能会导致一些意外的同步,因为printf应该是线程安全的。