线程锁定的变化

时间:2013-12-11 08:00:37

标签: c# multithreading locking

我正在编写一个可以同时运行多个请求的网络抓取程序。但是,有些请求需要连续发生,所以我首先想到的是围绕两个需要同时发生的请求并锁定其他请求。这种方法的问题在于,其他两个请求将相互锁定,但能够并行运行。

例如,我有四页需要网站上的数据:

  • example.com/page1
  • example.com/page2
  • example.com/page3
  • example.com/page4

当程序启动时,我启动三个线程:一个用于page1,一个用于page2和第3页,一个用于page4。第3页的请求必须在第2页请求后直接发生。对page1和page4的请求可以同时发生。

如果我不使用锁定,则可能会在page2和page3的请求之间请求page1或page4并导致问题。如果我对三个线程使用相同的锁,那么对page1的请求可能会阻止对page4的请求。

如何防止第2页和第3页之间发生请求,但允许其他请求同时发生?

2 个答案:

答案 0 :(得分:1)

您可以尝试使用信号量来控制对“页面请求”伪资源的访问。可以并发运行的请求只需要一个资源,必须运行的请求只需要所有资源。

如下所示:

private static Semaphore _pool;
private static readonly int kMaxConcurrrentPageRequesters = 4;  // or whatever number

// at some appropriate initialization point

_pool = new Semaphore(kMaxConcurrrentPageRequesters,kMaxConcurrrentPageRequesters);


// when a normal request is being made that can run concurrently:

_pool.WaitOne();
perform_page_request();
_pool.Release();


// when an exclusive page request is being made:

// maybe create a Semaphore wrapper that stores the max semaphore count
//   so that you can expose a `WaitAll()` method to replace this loop
for (int i = 0; i < kMaxConcurrrentPageRequesters; ++i) {
    _pool.WaitOne();
}
perform_exclusive_page_requests();
_pool.Release(kMaxConcurrrentPageRequesters);

答案 1 :(得分:0)

您可以延迟执行线程或让它们等待。例如,

var waitA = false;
var thread1 = new Thread((Action)(() => { while(!waitA) Thread.Sleep(0); /* do work here */ })).Start();
var thread2 = new Thread((Action)(() => { while(!waitA) Thread.Sleep(0); /* do work here */ })).Start();
// prepare data for threads? and start them
waitA = true;