1.獲取資源(獨佔模式)
acquire(int)
首先講解獨佔模式(exclusive)下的獲取/釋放資源過程,其入口方法為:
public final void acquire(int arg)
tryacquire(arg)為執行緒獲取資源的方法函式,在aqs中定義如下:
protected boolean tryacquire(int arg)
注:該方法是空方法,且由protected修飾,說明該方法需要由子類即自定義同步器來實現。
acquire()方法至少執行一次tryacquire(arg),若返回true,則acquire直接返回,
否則進入acquirequeued(addwaiter(node.exclusive), arg)方法。
實現的步驟:
第一步:addwriter()將當前執行緒加入到等待佇列的尾部,並標記為獨佔模式;
第一步:acquirequeued()使執行緒在等待佇列中獲取資源,直到獲取到資源返回,
若整個等待過程被中斷過,則返回true,否則返回false。
第三步:如果執行緒在等待過程中被中斷過,則先標記上,待獲取到資源後再進行自我中斷selfinterrupt(),將中斷響應掉。
涉及的函式:
1.tryacquire(int)
tryacquire嘗試以獨佔的模式獲取資源,如果獲取成功則返回true,否則直接返回false,
預設實現是丟擲unsupportedoperationexception,具體實現由自定義擴充套件了aqs的同步器來完成。
2.addwaiter(node)
addwaiter為當前執行緒以指定模式建立節點,並將其新增到等待佇列的尾部,其原始碼為:
private node addwaiter(node mode)
}// 常規插入
enq(node);
return node;
}再看enq(node)方法:
private node enq(final node node) else }}
}總結:可以看到,常規插入與快速插入相比:
第一點:常規插入是自旋過程(for(;;)),能夠保證節點插入成功;
第二點:比快速插入多包含了1種情況,即當前等待隊列為空時,需要初始化佇列,
即將待插入節點設定為頭結點,同時為尾節點(因為只有乙個嘛)。
注:常規插入與快速插入均依賴於cas,其實現依賴於unsafe類,具體**如下:
private final boolean compareandsethead(node update)
private final boolean compareandsettail(node expect, node update)
unsafe中的cas操作均是native方法,由計算機cpu的cmpxchg指令來保證其原子性。
3186 佇列練習 2
時間限制 1 s 空間限制 128000 kb 題目等級 gold 題解檢視執行結果 此題與佇列練習1相比改了2處 1加強了資料 2不保證隊空時不會出隊 給定乙個佇列 初始為空 只有兩種操作入隊和出隊,現給出這些操作請 輸出最終的隊頭元素。操作解釋 1表示入隊,2表示出隊 輸入描述 input de...
Codevs P3186 佇列練習2
題目描述 description 此題與佇列練習1相比改了2處 1加強了資料 2不保證隊空時不會出隊 給定乙個佇列 初始為空 只有兩種操作入隊和出隊,現給出這些操作請 輸出最終的隊頭元素。操作解釋 1表示入隊,2表示出隊 輸入描述 input description n 操作個數 n個操作 如果是入...
codevs 3186 佇列練習2
題目描述 description 此題與佇列練習1相比改了2處 1加強了資料 2不保證隊空時不會出隊 給定乙個佇列 初始為空 只有兩種操作入隊和出隊,現給出這些操作請 輸出最終的隊頭元素。操作解釋 1表示入隊,2表示出隊 輸入描述 input description n 操作個數 n個操作 如果是入...