考虑下一段代码-
#include <iostream>
using namespace std;
int sharedIndex = 10;
pthread_mutex_t mutex;
void* foo(void* arg)
{
while(sharedIndex >= 0)
{
pthread_mutex_lock(&mutex);
cout << sharedIndex << endl;
sharedIndex--;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main() {
pthread_t p1;
pthread_t p2;
pthread_t p3;
pthread_create(&p1, NULL, foo, NULL);
pthread_create(&p2, NULL, foo, NULL);
pthread_create(&p3, NULL, foo, NULL);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
pthread_join(p3, NULL);
return 0;
}
我简单地创建了三个
pthreads
并赋予它们所有相同的功能foo
,希望每个线程依次输出并减小sharedIndex
。但这是输出-
10
9
8
7
6
5
4
3
2
1
0
-1
-2
我不明白为什么
sharedIndex
时进程没有停止达到0。
sharedIndex
受mutex
保护。它变成0后如何访问?线程不应该直接跳到return NULL;
吗?编辑
此外,似乎只有第一个线程会减小
sharedIndex
。为什么不是每个线程都递减共享资源?
这是修复后的输出-
Current thread: 140594495477504
10
Current thread: 140594495477504
9
Current thread: 140594495477504
8
Current thread: 140594495477504
7
Current thread: 140594495477504
6
Current thread: 140594495477504
5
Current thread: 140594495477504
4
Current thread: 140594495477504
3
Current thread: 140594495477504
2
Current thread: 140594495477504
1
Current thread: 140594495477504
0
Current thread: 140594495477504
Current thread: 140594478692096
Current thread: 140594487084800
我希望所有线程都会减少共享源-意思是,每个contex开关,一个不同的线程都将访问该资源并执行其操作。
最佳答案
该程序的行为是不确定的。
您尚未初始化互斥锁。您需要调用pthread_mutex_init
或将其静态初始化:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
您在关键部分之外阅读了此变量:
while(sharedIndex >= 0)
这意味着您可以在另一个线程对其进行更新时读取垃圾值。在锁定互斥锁并对其具有独占访问权限之前,您不应阅读共享变量。
编辑:
似乎只有第一个线程递减
sharedIndex
那是因为行为不确定。解决以上问题,您应该看到其他线程正在运行。
使用您当前的代码,编译器可以假定
sharedIndex
从未被其他线程更新,因此它不必费心重新读取它,而只是让第一个线程运行十次,然后让其他两个线程运行一次每。这意味着,每个contex开关,一个不同的线程都将访问该资源并执行其操作。
无法保证pthread互斥体的行为公平。如果要保证每个线程依次运行的循环行为,则需要自己强加例如通过使用另一个共享变量(可能是条件变量)来说明要运行哪个线程,并阻塞其他线程,直到该线程轮到他们为止。