我在我的centos计算机上测试c ++ 11互斥。我尝试双重锁定此互斥锁以使其死锁。但是在我运行之后,一切都很好并且没有发生死锁。
import {PeopleService} from '../providers/people-service/people-service';
export class HomePage {
public people: any;
constructor(public peopleService: PeopleService){
}
}
编译器是g ++ 4.8.5 in centos 3.10.0-327.36.3.el7.x86_64:
#include <thread>
#include <mutex>
#include <iostream>
std::mutex m;
int main()
{
m.lock();
m.lock();
std::cout<<"i am ok"<<std::endl;
return 0;
}
答案 0 :(得分:9)
锁定已被同一个线程锁定的std::mutex
是未定义的行为,因此它可能会起作用,它可能会失败,它可能会喝掉所有啤酒并呕吐在沙发上。没有保证。
答案 1 :(得分:8)
如果您按原样调用lock
两次,则行为未定义
它按预期的方式工作确实是一种有效的未定义行为。
有关详细信息,请参阅here。
答案 2 :(得分:2)
到definition,僵局涉及至少两方。这是由许多作者,以及其他Hoare在他的开创性工作沟通顺序过程中制定的。这也在C ++标准定义中提醒(重点是我的):
17.3.8:死锁:一个或多个线程无法继续执行,因为 每个人都被阻止等待一个或多个其他来满足某些人 条件
Anthony Williams在 C ++并发行动
中给出了一个更具说明性的定义两个线程都无法继续,因为每个线程都在等待另一个线程释放它的互斥锁。这种情况称为死锁,它是必须锁定两个或多个互斥锁的最大问题。
因此,根据定义,您不能在单个进程中使用单个线程创建死锁。
该标准在互斥体上说:
30.4.1.2.1 / 4 [注意:如果拥有互斥对象的线程在该对象上调用lock(),程序可能会死锁。]
这是一份非规范性的说明。我认为这与标准的定义相矛盾。从术语的角度来看,锁定自身的进程处于阻塞状态。
但更重要的是,除了死锁术语的问题之外,还有“#34; MAY&#34;允许C ++实现的所述行为(例如,如果它不能在特定OS上检测冗余锁定获取)。但它根本不需要:我相信大多数主流C ++实现都会正常工作,就像你自己经历的一样。
如果您想体验真正的死锁,或者您只是想知道您的C ++实现是否能够检测到resource_deadlock_would_occur
错误,这里只是一个简短的例子。它可以很好但很有可能造成死锁:
std::mutex m1,m2;
void foo() {
m1.lock();
std::cout<<"foo locked m1"<<std::endl;
std::this_thread::sleep_for (std::chrono::seconds(1));
m2.lock();
m1.unlock();
std::cout<<"foo locked m2 and releases m1"<<std::endl;
m2.unlock();
std::cout<<"foo is ok"<<std::endl;
}
void bar() {
m2.lock();
std::cout<<"bar locked m2"<<std::endl;
std::this_thread::sleep_for (std::chrono::seconds(1));
m1.lock();
m2.unlock();
std::cout<<"barlocked m1 and releases m2"<<std::endl;
m1.unlock();
std::cout<<"bar is ok"<<std::endl;
}
int main()
{
std::thread t1(foo);
bar();
t1.join();
std::cout << "Everything went fine"<<std::endl;
return 0;
}
通过始终以相同的顺序锁定不同的互斥锁来避免这种死锁。