最近打算寫一個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)內(nèi)持有并加解鎖。另外一個是普通的流程函數(shù)。
代碼沒有拋出異常導致死鎖,起初以為是自己mutex不熟,用法有誤,但是反復查證,用法應(yīng)該沒問題。并且奇妙的是如果在加鎖前和解鎖后打印日志就會正常。
難道是死循環(huán)導致的嗎?
于是在Thread 2的unlock之后加了一句usleep:
mtx.unlock();
usleep(0);
在零X年的時候看過一篇帖子,說sleep(0)可以讓線程放棄當前獲得的cpu時間片。理論上這樣就可以產(chǎn)生一個中斷,讓其他線程得到執(zhí)行。
結(jié)果并沒有變化。
難道那篇帖子說的不對么。又改了下:
mtx.unlock();
usleep(1);
結(jié)果正常了,2個線程都正確的加鎖解鎖。
事后總結(jié),猜測就是因為Thread 2在解鎖之后,再次加鎖之前沒有能夠產(chǎn)生中斷的函數(shù),于是很快地又再次獲得了鎖,導致其他線程總是無法獲得鎖。這個問題和自旋鎖在單核機器上無法正常工作是一個原理。