java - AbstractQueuedSynchronizer中CAS的疑惑
問題描述
這段代碼是AQS框架中將當前節(jié)點入隊的操作。
Node pred = tail;if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) {pred.next = node;return node; }}
上面代碼中pred被賦值為尾節(jié)點,node為當前節(jié)點。我理解的將新節(jié)點插入鏈表尾處的邏輯應(yīng)當如下:node.prev = pred; node節(jié)點的前驅(qū)指向尾節(jié)點pred.next = node; 將尾節(jié)點的后繼設(shè)置為當前節(jié)點tail = node; 將node節(jié)點設(shè)置為尾節(jié)點對于上面代碼我的疑問如下:如果尾節(jié)點不為空,node節(jié)點的前驅(qū)會指向尾節(jié)點,然后調(diào)用CAS交換pred和node的值。此時pred(即tail)的值應(yīng)該已經(jī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 更新為當前node. pred.next 是將上一個尾部節(jié)點的next設(shè)置為當前node這邏輯不存在問題.
相關(guān)文章:
1. 在應(yīng)用配置文件 app.php 中找不到’route_check_cache’配置項2. html按鍵開關(guān)如何提交我想需要的值到數(shù)據(jù)庫3. HTML 5輸入框只能輸入漢字、字母、數(shù)字、標點符號?正則如何寫?4. javascript - 請教如何獲取百度貼吧新增的兩個加密參數(shù)5. Android中能不能判斷一個數(shù)據(jù)庫是create來的,還是open來的?6. gvim - 誰有vim里CSS的Indent文件, 能縮進@media里面的7. 跟著課件一模一樣的操作使用tp6,出現(xiàn)了錯誤8. PHP類屬性聲明?9. javascript - 求助canvas繪制馬賽克的問題,老是取色不準10. java - 安卓接入微信登錄,onCreate不會執(zhí)行
