最近打算寫一個curl的C++11封裝盛龄,使用Thread的時候出現(xiàn)了一個BUG,某一個線程始終持有一個鎖器虾,反復加鎖解鎖的過程讯嫂。而另外一個線程卡死在lock上。大致代碼如下:
std::mutex mtx;
//Thread 1
mtx.lock();
//...do something
mtx.unlock();
//Thread 2
do {
? ? mtx.lock();
? ? //...do something
? ? mtx.unlock();
}while(true);
Thread 2在一個死循環(huán)內持有并加解鎖兆沙。另外一個是普通的流程函數(shù)欧芽。
代碼沒有拋出異常導致死鎖,起初以為是自己mutex不熟葛圃,用法有誤千扔,但是反復查證,用法應該沒問題库正。并且奇妙的是如果在加鎖前和解鎖后打印日志就會正常曲楚。
難道是死循環(huán)導致的嗎?
于是在Thread 2的unlock之后加了一句usleep:
mtx.unlock();
usleep(0);
在零X年的時候看過一篇帖子褥符,說sleep(0)可以讓線程放棄當前獲得的cpu時間片龙誊。理論上這樣就可以產(chǎn)生一個中斷,讓其他線程得到執(zhí)行喷楣。
結果并沒有變化趟大。
難道那篇帖子說的不對么。又改了下:
mtx.unlock();
usleep(1);
結果正常了铣焊,2個線程都正確的加鎖解鎖逊朽。
事后總結,猜測就是因為Thread 2在解鎖之后曲伊,再次加鎖之前沒有能夠產(chǎn)生中斷的函數(shù)叽讳,于是很快地又再次獲得了鎖,導致其他線程總是無法獲得鎖。這個問題和自旋鎖在單核機器上無法正常工作是一個原理岛蚤。