我的问题是我不知道如何正确使用互斥锁。我了解它在理论上是如何工作的,但是我不知道为什么它在我的代码中不起作用。我想,如果我在var上使用互斥锁,它将被阻塞,直到被解锁。尽管如此,看来我仍然有一场数据竞赛。
我试图在类中定义一个互斥体和一个互斥体,它们通过引用传递给我。不知何故,这没用。
class test {
public:
void dosmth(std::mutex &a);
int getT(){return t;};
private:
int t = 0;
};
void test::dosmth(std::mutex &a) {
for(;;){
a.lock();
t++;
if(t==1000){
t=0;
}
a.unlock();
}
}
int main() {
test te;
std::mutex help;
std::thread t(&test::dosmth, std::addressof(te), std::ref(help));
for(;;){
for (int i = 0; i <te.getT() ; ++i) {
std::cout<<te.getT()<<std::endl;
}
}
}
结果应该是我得到了一些输出,所以现在我可以使用了。
答案 0 :(得分:2)
正如Michael所提到的,您应该同步读取器和写入器,以避免未定义的行为。代替传递mutex
作为参数,一种常见的模式是使mutex
成为对象(te
)的成员,每次都锁定和解锁(最好使用lock_gaurd
您可以输入成员函数(修改对象的内部状态),而不是手动锁定和解锁。这是一些伪代码:
class Foo{
std::mutex m; // reader and writer are sync'ed on the same mutex
int data_to_sync;
public:
int read(){
lock_gaurd<mutex> lg(m); //RAII lock
return data_to_sync;
//automagically released upon exit
}
void write(){
lock_gaurd<mutex> lg(m);
data_to_sync++;
}
};
答案 1 :(得分:1)
仅当互斥锁用于调节所有 critical sections的代码输入时,互斥锁才能保证互斥。就您而言,您的第二个线程在主线程读取同一对象的值时修改了对象te.t
的值。但是,只有一个线程正在使用互斥锁来保护对te.t
的访问。对象te.t
不是原子的。因此,您将面临数据争用,从而导致行为未定义[intro.races]/21。
您还必须在主for(;;)
循环中锁定和解锁互斥锁,例如:
for(;;){
help.lock();
for (int i = 0; i <te.getT() ; ++i) {
std::cout<<te.getT()<<std::endl;
}
help.unlock();
}
或更佳,使用std::lock_guard:
for(;;){
std::lock_guard lock(help);
for (int i = 0; i <te.getT() ; ++i) {
std::cout<<te.getT()<<std::endl;
}
}
答案 2 :(得分:0)
我想如果我在var上使用互斥锁...
您不要在“变量上”使用互斥量。锁定互斥锁可以防止其他线程同时锁定同一互斥锁,但是 not 不会阻止其他线程访问任何特定变量。
如果您希望使用互斥锁来保护一个变量(或更常见的是多个变量),以防止多个线程同时访问该变量,则由您决定您不会编写任何代码来访问变量而不先锁定互斥锁。