考虑下一段代码 -
#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后访问它? Aren的线程应该直接跳到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
我希望所有的线程都会减少共享源 - 意思是,每个上下文切换,一个不同的线程将访问资源并做其事。
答案 0 :(得分:4)
此程序的行为未定义。
您尚未初始化互斥锁。您需要致电pthread_mutex_init
或静态初始化它:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
您在关键部分之外阅读此变量:
while(sharedIndex >= 0)
这意味着您可以在另一个线程更新它时读取垃圾值。在锁定互斥锁并拥有对它的独占访问权之前,不应该读取共享变量。
修改强>
似乎只有第一个线程会减少
sharedIndex
那是因为未定义的行为。修复上面的问题,你应该看到其他线程运行。
使用当前代码,编译器可以假设sharedIndex
永远不会被其他线程更新,因此它不会重新读取它,只是让第一个线程运行十次,然后其他两个线程各运行一次。
意思是,每个上下文切换,一个不同的线程将访问资源并做其事情。
无法保证pthread互斥锁的行为公平。如果你想保证每个线程轮流运行的循环行为,那么你需要自己强加,例如:通过另一个共享变量(可能是一个条件变量)来说明要运行哪个线程,并阻止其他线程直到轮到它们。
答案 1 :(得分:3)
线程将挂在pthread_mutex_lock(&mutex);
等待获取锁定。一旦一个线程递减到0并释放锁定,那么等待锁定的下一个线程将继续它的业务(使值为-1),并且对于下一个线程(使值-2)相同。 / p>
您需要在检查值和锁定互斥锁时更改逻辑。
答案 2 :(得分:3)
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;
}
根据此代码,sharedIndex
是所有线程的共享资源。
因此,对它的每次访问(读取和写入)都应该由互斥锁包装。
否则假设所有线程同时采样sharedIndex
且其值为1
的情况。
然后,所有主题都会进入while
循环,每个主题将sharedIndex
减少一个,最后将-2
缩小为bool is_positive;
do
{
pthread_mutex_lock(&mutex);
is_positive = (sharedIndex >= 0);
if (is_positive)
{
cout << sharedIndex << endl;
sharedIndex--;
}
pthread_mutex_unlock(&mutex);
}while(is_positive);
。
修改强>
可能的修复(作为可能的选项之一):
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
<强> EDIT2 强>
请注意,您必须初始化互斥锁:
<BASE>