Fork Join框架之雙端佇列

2021-09-09 03:04:55 字數 1910 閱讀 4102

forkjoinpool管理著forkjoinworkerthread執行緒,forkjoinworkerthread執行緒內部有乙個雙端佇列,這個雙端佇列主要由乙個陣列queue、陣列下標queuebase、陣列上標queuetop三個值保證。

forkjointask<?> queue:陣列的大小必須是2的n次方,方便將取模轉換為移位運算;

int queuetop:標識下乙個被push或者pop的位置,這個值只會被當前執行緒修改,因些沒有加volatile修飾;

volatile int queuebase:下乙個可以被其他執行緒steal的位置,由於其他執行緒會修改這個值,所以用volatile修飾保證可見性。

當向執行緒中新增任務時,有可能會導致陣列滿的情況,如下**所示:

final void pushtask(forkjointask<?> t) 

}

其中s代表queuetop的值,m為陣列長度-1,當s == m時,也就是queue陣列中都放滿任務了,這時需要對陣列進行擴容。

private void growqueue() 

}}

從以上擴容**可以看出,最大容量不能超過maximum_queue_capacity(1 << 24),最小不能小於初始值。每次擴容為先前大小的2倍,將原始陣列複製到新陣列中,同時將舊陣列置null。

擴容的過程中,queuebase和queuetop並不需要變化。

向執行緒佇列中新增乙個任務,或者向執行緒池新增乙個任務時,如果這個任務是乙個forkjointask例項,就會做入佇列的操作。前面已有這段**,這裡簡要分析一下

long u = (((s = queuetop) & (m = q.length - 1)) << ashift) + abase;

unsafe.putorderedobject(q, u, t);

queuetop = s + 1;

第一行,找到queuetop在陣列中的位置

第二行,用新任務填充queuetop所在位置

第三行,queuetop加1.

final void exectask(forkjointask<?> t) 

++stealcount;

currentsteal = null;

}

注意locallyfifo 這個屬性,是否對自己的佇列採用fifo策略,預設為false,即預設從queuetop一端取任務。如果這個值為false,則從queuebase一端取資料。這個值可以通過forkjoinpool類的asyncmode屬性加以修改。

final forkjointask<?> locallydeqtask() }}

return null;

}private forkjointask<?> poptask() }}

return null;

}

關鍵兩句話:

queuebase = b + 1:fifo策略每次從queuebase取任務,每取乙個,queuebase增加1;

--s,queuetop = s:lifo策略每次從queuetop取任務,每取乙個,queuetop減1。

以下是work-stealing的核心**

for (;;) 

}

1、瞄到第i個位置這個任務,i = (q.length-1) & b,i其實就是queuebase在陣列中所在的位置;

2、將這個位置上的任務設定為null,並增加queuebase的值,設定stealhint表示你的東西被我偷了;

3、儲存先前的currentsteal值,設定currentsteal為這個偷來的task,然後執行這個task,執行完後,恢復currentsteal的值。

STL之雙端佇列

deque雙向佇列是一種雙向開口的連續 線性空間 可以高效的在頭尾兩端插入和刪除元素,deque在介面上和 vector 非常相似,下面列出deque的常用成員函式 deque.c c.assgin beg,end c.assgin n,elem c.at idx c.front c.back c....

C STl之雙端佇列

deque與vector非常相似,不僅可以在尾部插入和刪除元素,還可以在頭部插入和刪除。不過當考慮到容器元素的記憶體分配策略和操作效能時,deque相對vector較為有優勢。標頭檔案 include 1 deque 建立乙個沒有任何元素的deque物件。deque d 2 deque size t...

佇列 雙端佇列

1.佇列 佇列是遵循先進先出 fifo,也稱為先來先服務 原則的一組有序的項。佇列在尾部新增新 元素,並從頂部移除元素。最新新增的元素必須排在佇列的末尾 class queue 向佇列新增元素 enqueue element 檢查佇列是否為空並獲取它的長度 isempty 從佇列移除元素 deque...