靈活的鎖
std::unique_lock
unique_lock比lock_guard更加靈活,它擁有成員函數(shù)lock、unlock、try_lock,但占用空間更大,速度也稍慢?!八梨i”一節(jié)中最后的代碼也可以像下面這樣寫:

std::unique_lock實(shí)例沒(méi)有與自身相關(guān)的互斥量,即一個(gè)unique_lock對(duì)象并不擁有一個(gè)特定的互斥量,它可以通過(guò)移動(dòng)操作來(lái)獲得對(duì)互斥量的所有權(quán),并在不同的unique_lock實(shí)例之間傳遞。在某些情況下,這種轉(zhuǎn)移是自動(dòng)發(fā)生的,例如當(dāng)函數(shù)返回一個(gè)unique_lock實(shí)例時(shí)。但在其他情況下,需要顯式地調(diào)用std::move來(lái)執(zhí)行移動(dòng)操作。

鎖的粒度
鎖的粒度用來(lái)描述通過(guò)一個(gè)鎖保護(hù)著的數(shù)據(jù)量大小。一個(gè)細(xì)粒度鎖(a fine-grained lock)能夠保護(hù)較少的數(shù)據(jù)量,一個(gè)粗粒度鎖(a coarse-grained lock)能夠保護(hù)較多的數(shù)據(jù)量。選擇粒度對(duì)于鎖來(lái)說(shuō)很重要,為了保護(hù)對(duì)應(yīng)的數(shù)據(jù),確保鎖有能力保護(hù)這些數(shù)據(jù)也很重要。
如果很多線程正在等待同一個(gè)資源,當(dāng)有線程持有鎖的時(shí)間過(guò)長(zhǎng),就會(huì)增加等待的時(shí)間。std::unique_lock的靈活性在此時(shí)就可以發(fā)揮作用。當(dāng)線程暫時(shí)不需要訪問(wèn)共享數(shù)據(jù)時(shí),可以調(diào)用unlock;當(dāng)再次需要訪問(wèn)共享數(shù)據(jù)時(shí),可以再調(diào)用lock。
Case :

不僅需要讓鎖能鎖住合適粒度的數(shù)據(jù),還要控制鎖的持有時(shí)間,以及判斷哪些操作在執(zhí)行的同時(shí)能夠擁有鎖。一般情況下,執(zhí)行必要的操作時(shí),盡可能將持有鎖的時(shí)間縮減到最小。
Case :

在上述代碼中比較兩個(gè)Instance對(duì)象時(shí),由于int的拷貝很容易,所以選擇先將i和j的content分別賦值給vi和vj后,再對(duì)vi和vj進(jìn)行比較。這樣做的好處是減少了鎖持有的時(shí)間(僅在執(zhí)行getContent函數(shù)時(shí)持有鎖),并且一個(gè)鎖只持有一次,消除了死鎖的可能性。但是這樣做的后果是——這兩個(gè)值在讀取之后,可能會(huì)被任意的方式所修改,比較的結(jié)果可能為true,但實(shí)際上這兩個(gè)值相等的情況可能僅僅發(fā)生在某個(gè)瞬間。假設(shè)剛剛完成對(duì)vi的賦值后,此時(shí)該線程既不持有i的鎖,也不持有j的鎖,如果有另一個(gè)線程在此刻獲取了i和j的鎖,執(zhí)行了交換i和j的content的操作,那么之后vj也將被賦予和vi相同的值,比較也就失去了意義。
Warning:當(dāng)你持有鎖的時(shí)間沒(méi)有達(dá)到整個(gè)操作時(shí)間,就會(huì)讓自己處于條件競(jìng)爭(zhēng)的狀態(tài)。
在這個(gè)例子中,需要尋找一個(gè)合適的機(jī)制,去替換std::mutex。