2009-09-23 24 views
2

解決

我改變了BFS :: directory_iterator隊列以一個std ::串隊列,並且令人驚訝地解決了這個問題。boost scoped_lock。這個鎖嗎?


嗨,我有一種直覺,認爲我做錯了事。

我已經實現(或試圖)線程池模式。

N個線程從隊列中讀取,但我遇到了一些麻煩。這是我得到的:

//inside a while loop 
bool isEmpty; 
bfs::directory_iterator elem; 

{ 
    boost::mutex::scoped_lock lock(this->queue_mutex); 
    isEmpty = this->input_queue.isEmpty(); 

    if (!isEmpty){ 

     elem= *(this->input_queue.pop()); 
    } 
    else{ 
     continue; 
    } 
} 

scoped_lock仍然在if內部工作嗎?我開始相信它不會(在運行很多測試之後)。如果沒有,是否有任何有限的方式來做到這一點(即不是明確的鎖解鎖方式)

在此先感謝。

更新

,增加元素到隊列中的代碼看起來是這樣的

//launches the above code, passing a reference to mutex and queue. 
    Threads threads(queue,queue_mutex); 

    for (bfs::directory_iterator dir_it:every file in directory){ 
     boost::mutex::scoped_lock lock(queue_mutex); 

     queue.push(dir_it); 


    } 

林放置COUT來控制POP操作的文件名,並且如果我推2個文件(文件1)和(文件2) ,並使用2個線程,我得到兩個「文件2」。

class Threads{ 

    boost::thread::thread_group group; 
    Thread (N){ 

    //also asigns a reference to a queue and a mutex. 
    for(i 1..N){ 
     //loop is posted above. 
     group.add(new boost::thread(boost::bind(&loop,this))); 
    } 
    } 
}; 
+2

代碼似乎罰款。您的程序以何種方式表現不正確? – avakar 2009-09-23 19:18:28

+0

您發佈的代碼的確看起來不錯。如果你問:「這是否會使用更窄範圍的鎖(在'if'中)?」,請澄清一下。 – Novelocrat 2009-09-23 19:24:37

+0

鎖定真的看起來不錯 - 你是否正確地得到了「'file1'」和「'file2'」,如果你像上面那樣填充隊列,但是讀取它是非線程的(即按順序)? – hjhill 2009-09-23 20:49:01

回答

1

發佈的代碼顯示正常 - 如果您發現問題,可能還有其他需要鎖定的地方,而不是(例如將代碼添加到隊列中的代碼)。

0

沒有,鎖也不會,如果它的if內移動上班,因爲那裏將是對反對空虛檢查的競爭條件。最後一個元素可能在檢查和鎖定之間被刪除。

+0

-1,你在說什麼?在獲得鎖定之後執行對空虛的測試。 – avakar 2009-09-23 19:17:00

+0

這個問題問,如果鎖是在'if'裏面的話,它是否仍然可以工作,至少據我瞭解。如果我的理解錯誤,我希望OP會澄清,我會刪除它。 – Novelocrat 2009-09-23 19:22:48

+0

@Novelcrat。我的意思是,如果if內部的代碼,如上所述,將被鎖定。對不起,如果我造成混淆 – Tom 2009-09-23 20:09:34

0

我會將鎖添加到隊列中......管理隊列外部的鎖是非常棘手的,往往會混淆代碼,但是由於解鎖的數據結構暴露出來,所以它也相當脆弱。

對於隊列來說,這種模式似乎正在獲得實用性,它是try_pop & try_push方法。 .NET的並行擴展與System.Collections.Concurrent.ConcurrentQueue一起使用這種模式。

這可以通過無鎖隊列或通過簡單地將隊列嵌入並將其鎖定在具有適當接口的容器中來完成。安東尼威廉姆斯有一個很好的職位,如何做到這一點與std ::隊列here

你的代碼可以是這樣的:

//inside a while loop 
bfs::directory_iterator elem; 

while (this->input_queue.pop(*elem)) 
{ 
    ... // do something 
} 
相關問題