【发布时间】:2020-02-29 10:36:56
【问题描述】:
我想编写一个简单的 C 程序来更好地理解信号量。有两个线程,它们都调用相同的函数。第一个线程,增加全局变量,第二个线程,减少全局变量。
我试图在第一个线程完成工作之前阻止第二个线程使用该函数。但我仍然得到错误的答案:-2000。看起来两个线程都有偏移量-1。我该如何解决这个问题,使输出始终为 0?我认为函数内部的 sem_wait 应该阻塞第二个线程,直到第一个线程结束。因此偏移量应该保持为 1。
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_LOOPS 1000
long long counter = 0;
sem_t sem;
sem_t sem1;
void* counting_thread(void* arg) {
sem_wait(&sem);
int offset = *(int*) arg;
int i;
for(i = 0; i < NUM_LOOPS; i++){
//sem_wait(&sem);
counter += offset;
printf("offset = %d\n", offset1);
//sem_post(&sem);
}
sem_post(&sem);
pthread_exit(NULL);
}
int main() {
sem_init(&sem, 0, 1);
pthread_t th1;
int offset = 1;
pthread_create(&th1, NULL, &counting_thread, &offset);
//sem_post(&sem1);
pthread_t th2;
offset = -1;
pthread_create(&th2, NULL, &counting_thread, &offset);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
printf("Finnal counter value: %lld\n", counter);
sem_destroy(&sem);
return 0;
}
【问题讨论】:
-
pthread_create将指向变量的指针作为参数传递给线程。你指向同一个变量,offset用于两个线程,这意味着根据你重新分配它的时间,它们可能会得到相同的值传入。尝试为第二个线程创建一个单独的变量,而不是重新分配一个已经传递的变量到第一个。 -
是的,因为线程使用相同的地址空间,这就是问题所在。但是应该有一个只使用信号量的解决方案。
-
您对
offset的重新分配发生在信号量锁之外(以及启动的线程之外),因此无论您在线程内锁定多少,这都是一种竞争条件。 -
即使我在第二个线程的函数调用和变量更新周围放置一个信号量(这样偏移量不会被更新),我得到一个错误的结果。
-
您的结果最有可能发生的事情(对比赛条件的保留相当不确定)是; 1)您将 1 分配给偏移量。 2)您告诉线程 1 在未来某个时间启动 3)您将 -1 分配给偏移量 4)您告诉线程 2 在未来某个时间启动 5)线程都启动,并且都获得偏移量的当前值 -1作为参数。
标签: c multithreading operating-system pthreads semaphore