【发布时间】:2016-04-08 21:53:35
【问题描述】:
标题可能看起来不是特别清楚,但代码说明了自己:
int shared_variable;
int get_shared_variable() {
int result;
pthread_mutex_lock(&shared_variable_mutex);
result = shared_variable;
pthread_mutex_unlock(&shared_variable_mutex);
return result;
}
void* thread_routine(void *arg) {
while (get_shared_variable() < 5000) {
printf();
printf();
sleep(2);
int i = 0;
while (pthread_mutex_trylock(&foo_mutexes[i]) != 0) {
i++;
pthread_mutex_lock(&foo_count_mutex);
if (i == foo_count) {
pthread_mutex_unlock(&foo_count_mutex);
sleep(1); // wait one second and retry
i = 0;
}
pthread_mutex_unlock(&foo_count_mutex);
}
pthread_mutex_lock(&shared_variable_mutex);
shared_variable += 10;
pthread_mutex_unlock(&shared_variable_mutex);
}
return NULL;
}
我将thread_routine 传递给pthread_create(相当标准),但结果的同步存在问题。基本上,问题是第一个线程检查while条件,它通过了,然后另一个线程检查它,它也通过了。但是,当第一个线程完成并且shared_variable 达到 5000 时,第二个线程尚未完成并且它加起来另一个 10,最终结果变为 5010(或 NUM_OF_THREADS - 1 * 10,如果我运行两个以上)结束,而整个过程应该在5000结束。
另一个问题是,在// do some work 中,我在屏幕上输出了一些内容,因此循环中的整个内容在数据库术语中应该作为事务 工作。我似乎无法弄清楚如何解决这个问题,但我想我缺少一些简单的东西。提前致谢。
【问题讨论】:
-
在关键部分完成之前,您不能释放互斥锁。您的关键部分需要包含both 读取和写入变量,并且需要在单个 关键部分中完成。
-
@kaylum,这是否意味着关键部分应该是整个循环,并且考虑到我在
// do some work有很多工作,不会阻塞其他线程这么长时间来击败拥有它们的目的是什么? -
这取决于你想如何安排它。通常,在您的情况下,循环体将是 CS。不包括循环条件本身。但是,是的,如果“一些工作”很长,那么可能会有问题。但这是一个性能问题,我们只讨论这个问题的正确性。如果您想讨论性能,那么您需要提出一个新问题,以准确显示“某些工作”做了什么,然后其他人才能解释如何更好地构建线程。
-
一般原则是使 CS 尽可能短,同时仍保持正确性。在您的情况下,您已经简短但不正确。但在不知道“某些工作”是什么的情况下,我们无法告诉您它的部分/全部是否属于 CS,或者是否可以完全从 CS 中排除。
-
我知道原理,这就是为什么我不喜欢包装这么多代码的原因。无论如何,我已经用更详细的代码编辑了这个问题。
sleep()调用几乎是真实工作的准确模拟时间。
标签: c multithreading concurrency