在代码中使用互斥锁:
class Bank{
public:
Bank():counter(0){};
void addBankAccount(){
unique_lock<mutex> m ( g_Mtx );
for( int i = 0; i < 1000; i++){
counter++;
}
}
int getCounter(){
return counter;
}
private:
int counter;
mutex g_Mtx;
};
int calculate(){
Bank b;
thread t1(&Bank::addBankAccount,&b);
thread t2(&Bank::addBankAccount,&b);
t1.join();
t2.join();
if( b.getCounter() != 2000)
cout << "Error value is " << b.getCounter() << endl;
}
int main()
{
for(int i = 0; i < 10000; i++)
calculate();
return 0;
}
互斥锁本身是必要的,以保持正确的结果。
如果没有互斥量我没有错,那会产生一些结果:
THREAD 1 | THREAD 2
|
1) load value of counter in register | 2) load value of counter in register
value in register is 0 | value in register is 0
3) increment register( value is 1) | 4) increment register( value is 1)
4) update variable, value of | 5) update variable, value of
counter is set to 1 again counter is set to 1
(标记1)... 5)应指示计算机可以处理指令的顺序。因此省略一些增量。但我的问题是关于互斥锁本身。
当两个线程正在运行时,例如相同的功能
void addBankAccount(){
unique_lock<mutex> m ( g_Mtx );
for( int i = 0; i < 1000; i++){
counter++;
}
}
在我的承诺中,当声明互斥锁并锁定锁定时,想要访问锁定数据的线程“暂停”并在解锁时“恢复”并且可以访问数据(想要使用该数据的线程在队列中)。但是当互斥锁在另一个块范围内时会发生什么?例如:
void addBankAccount(){
{
unique_lock<mutex> m ( g_Mtx );
for( int i = 0; i < 1000; i++){
counter++;
}
// some other piece of code
}
这会改变什么吗?我已经看到了这种用法,我没有看到它与函数的原始声明有何不同。当线程想要访问被锁定的数据时,它是否“暂停”整个线程,还是仅仅“暂停”块范围,所以在这种情况下它会跳转到
// some other piece of code
当锁被解锁时,它会跳回到范围内的循环中?
我已经阅读了很多关于互斥的文章,但我仍然对此感到困惑。
而且,我对互斥体的理解可能是错误的。
所有解释都表示赞赏。
由于
答案 0 :(得分:1)
在您的示例中,没有区别。将锁嵌入内部块的原因是可以提前释放互斥锁。
void addBankAccount(){
int count_save;
{
unique_lock<mutex> m ( g_Mtx );
for( int i = 0; i < 1000; i++){
counter++;
}
count_save = counter;
} // mutex will be released here
// Still inside addBankAccount, but now it's safe to do IO
std::cout << "Bank account is now" << count_saved;
}
您经常发现要释放互斥锁,然后执行其他处理。例如,IO很慢,并涉及获取其他锁;在持有互斥锁时不要这样做是个好主意。
请注意,在示例中,count_save
是一个局部变量,因此对于线程是私有的 - 它不是由互斥锁保护的共享状态的一部分。一旦互斥锁被释放,必须不要触摸任何共享状态。
另请注意,由于缺少同步,帐户状态可能会在输出发生之前发生更改。实际上,无法保证较早更改的输出将在稍后更改的输出之前发生。 (因此,这可能不是一个特别好的例子!)