我想做的是让每个线程在main更改其他线程的结构之前使用临界区从结构体中复制信息。
#include <iostream>
#include <pthread.h>
using namespace std;
struct foo
{
public:
int var;
int *turn;
int index;
pthread_mutex_t *bsem;
pthread_cond_t *waitTurn;
};
void *threadFunc(void *arg) {
int var;
foo *workingVar = (foo *)arg;
pthread_mutex_lock(workingVar->bsem);
while (*workingVar->turn != workingVar->index)
pthread_cond_wait(workingVar->waitTurn, workingVar->bsem);
var = workingVar->var;
*workingVar->turn++;
pthread_cond_broadcast(workingVar->waitTurn);
pthread_mutex_unlock(workingVar->bsem);
cout << var << endl;
return nullptr;
}
int main() {
int turn = 0, NTHREADS = 5;
foo mainStruct;
pthread_mutex_t bsem;
pthread_mutex_init(&bsem, NULL);
pthread_cond_t waitTurn = PTHREAD_COND_INITIALIZER;
mainStruct.bsem = &bsem;
mainStruct.waitTurn = &waitTurn;
mainStruct.turn = &turn;
pthread_t tid[NTHREADS];
for (int i = 0; i < NTHREADS; i++) {
mainStruct.index = i;
mainStruct.var = i;
pthread_create(&tid[i], nullptr, threadFunc, &mainStruct);
}
for (int i = 0; i < NTHREADS; i++)
pthread_join(tid[i], NULL);
}
上面的代码来自一个线程函数。我试图让线程等待,直到使用pthread_cond_wait是他们的"turn",然后一旦条件为真,从main传递的结构信息将被复制到局部变量中,并将增加转动并退出临界区(也不使用全局变量,所以互斥锁和条件变量是使用指针通过结构体传递的)。Turn初始化为0,index是线程号(按照创建的顺序)。
此进程死锁,超时。
如果需要更多的上下文/信息,请让我知道,这是我的第一个堆栈溢出问题。
我在mainStruct.index
上看到竞争条件。主线程在没有锁的情况下修改它,多个线程在锁下访问它。因此,如果第一个线程启动得很快,它将与循环生成线程交互。
看起来您计划有多个Foo
实例,但是您只有一个。所以想象一下场景:
- 主线程到达第一个join
- 其他线程已创建,但尚未开始运行
- 在该点
mainStruct.index
的值为4
! - 第一个线程开始执行并获取锁。
turn
为0
,workingVar->index
为4
(见第3点) 所以线程进入pthread_cond_wait并等待- 下一个线程执行与第4-6点相同
- 所有侧线程处于等待状态
所有线程都在等待没有人调用pthread_cond_broadcast
条件*workingVar->turn != workingVar->index
总是true
你的代码是用C
而不是C++
写的。唯一的C++
是使用std::cout
!试着用std::thread
重写这个,它会自己修复(如果你通过值传递参数)。
这是我的c++版本