2009-09-23 25 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 
} 
相关问题