java - AbstractQueuedSynchronizer中CAS的疑惑
問題描述
這段代碼是AQS框架中將當(dāng)前節(jié)點入隊的操作。
Node pred = tail;if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) {pred.next = node;return node; }}
上面代碼中pred被賦值為尾節(jié)點,node為當(dāng)前節(jié)點。我理解的將新節(jié)點插入鏈表尾處的邏輯應(yīng)當(dāng)如下:node.prev = pred; node節(jié)點的前驅(qū)指向尾節(jié)點pred.next = node; 將尾節(jié)點的后繼設(shè)置為當(dāng)前節(jié)點tail = node; 將node節(jié)點設(shè)置為尾節(jié)點對于上面代碼我的疑問如下:如果尾節(jié)點不為空,node節(jié)點的前驅(qū)會指向尾節(jié)點,然后調(diào)用CAS交換pred和node的值。此時pred(即tail)的值應(yīng)該已經(jīng)是當(dāng)前節(jié)點node的值了,再執(zhí)行pred.next=node是什么意思呢,這是否存在邏輯問題?
問題解答
回答1:TZ可能對compareAndSetTail的理解有誤。
private final boolean compareAndSetTail(Node expect, Node update) {return unsafe.compareAndSwapObject(this, tailOffset, expect, update); }
在AbstractQueuedSynchronizer的tailOffset位置比較pred的值和期望的node值,如果相同則更新tailOffset位置的值。
static { tailOffset = unsafe.objectFieldOffset (AbstractQueuedSynchronizer.class.getDeclaredField('tail')); ...}
compareAndSetTail(pred, node) 這句代碼執(zhí)行完成之后,被修改只是對象AbstractQueuedSynchronizer的tailOffset的值,也就是成員變量tail的值,對于pred的值沒有任何影響。至于雙向鏈表,尾部插入,邏輯上沒有問題。
回答2:這個設(shè)計是一個雙向鏈表.B.prev == AA.next == B
compareAndSetTail 設(shè)置成功只是將 tail 更新為當(dāng)前node. pred.next 是將上一個尾部節(jié)點的next設(shè)置為當(dāng)前node這邏輯不存在問題.
相關(guān)文章:
1. objective-c - 微信快捷發(fā)送最近一張圖片是如何實現(xiàn)的?2. PHP單例模式3. mysql 5萬張表 導(dǎo)出成sql 不要內(nèi)容,只要結(jié)構(gòu),非常慢。如何解決啊?4. mysql - eclispe無法打開數(shù)據(jù)庫連接5. 數(shù)據(jù)庫 - mysql中有沒查看數(shù)據(jù)大小的函數(shù)??6. mysql無法刪除字段(錯誤1091),但是對該字段設(shè)置主鍵后就可刪除,為什么?7. 老師 我是一個沒有學(xué)過php語言的準畢業(yè)生 我希望您能幫我一下8. mysql如何配置遠程php外網(wǎng)鏈接數(shù)據(jù)庫9. 導(dǎo)入數(shù)據(jù)庫不成功10. mysql如何判斷數(shù)據(jù)不存在則插入呢?
