網(wǎng)上很容易找到一個(gè)用boost::shared_mutex來(lái)作為讀寫鎖的例子:
- typedef boost::shared_mutex rwmutex;
- typedef boost::shared_lock<rwmutex> readLock;
- typedef boost::unique_lock<rwmutex> writeLock;
typedef boost::shared_mutex rwmutex;
typedef boost::shared_lock<rwmutex> readLock;
typedef boost::unique_lock<rwmutex> writeLock;
一直沒(méi)有懷疑過(guò)這個(gè)做法,直到最近項(xiàng)目中出現(xiàn)一個(gè)死鎖問(wèn)題,查了很久才發(fā)現(xiàn)是上面這種寫法造成的。
寫測(cè)試代碼還原死鎖的情景如下:
- #include <boost/thread/shared_mutex.hpp>
- #include <boost/thread/shared_lock_guard.hpp>
- #include <boost/thread.hpp>
- #include <iostream>
- #include <Windows.h>
- using namespace std;
- typedef boost::shared_mutex rwmutex;
- typedef boost::shared_lock<rwmutex> readLock;
- typedef boost::unique_lock<rwmutex> writeLock;
-
- rwmutex m_mutex;
- void func1()
- {
- writeLock lock1(m_mutex);
- cout << "fffffffffffffff" << endl;
- }
-
- int main()
- {
- {
- boost::thread tt(func1);
- readLock lock(m_mutex);
- {
- Sleep(3000);
- readLock lock(m_mutex);
- cout << "rrrrrrrrrrrrrrrrrr" << endl;
- }
- }
- }
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/shared_lock_guard.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <Windows.h>
using namespace std;
typedef boost::shared_mutex rwmutex;
typedef boost::shared_lock<rwmutex> readLock;
typedef boost::unique_lock<rwmutex> writeLock;
rwmutex m_mutex;
void func1()
{
writeLock lock1(m_mutex);
cout << "fffffffffffffff" << endl;
}
int main()
{
{
boost::thread tt(func1);
readLock lock(m_mutex); // 加讀鎖
{
Sleep(3000); // 故意睡眠3秒將線程切換出去
readLock lock(m_mutex); // 醒來(lái)后再次加讀鎖
cout << "rrrrrrrrrrrrrrrrrr" << endl;
}
}
}
情形描述如下:
1:主線程先給m_mutex加讀鎖。
2:主線程故意睡眠3秒將執(zhí)行權(quán)限切換出去。
3:func1線程獲得執(zhí)行機(jī)會(huì),嘗試加寫鎖被掛起。因?yàn)橹骶€程已經(jīng)有一個(gè)讀鎖占用,寫鎖必須等待這個(gè)讀鎖釋放才能進(jìn)入。
4:主線程睡眠3秒醒來(lái),后續(xù)代碼想獲取一個(gè)讀鎖。由于這個(gè)時(shí)候已經(jīng)有一個(gè)寫鎖在等待進(jìn)入,那么這個(gè)讀鎖排隊(duì)在寫鎖后面,同樣被掛起。
5:主線程和func1線程都被掛起了,發(fā)生死鎖。
上面的測(cè)試代碼,如果中間沒(méi)有sleep(3000),出現(xiàn)死鎖的概率很低,但總歸是存在死鎖的可能。
總結(jié):
以前一直認(rèn)為readLock鎖和遞歸鎖一樣,在同一個(gè)線程多次進(jìn)入沒(méi)有關(guān)系才會(huì)造成上面的死鎖出現(xiàn)。所以,boost::shared_lock使用要小心,千萬(wàn)不要同一個(gè)線程多次進(jìn)入。