使用两个信号量实现主线程和线程池同步

目前项目里面有个需求,需要多线程操作数据库,等待数据库操作完毕之后,主线程才能继续执行以后的操作。

想了想,最后决定使用两个信号量来完成这个需求。

具体需求如下 :

  1. 操作数据库的线程最多20个
  2. 主线程必须等待所有操作数据库的线程返回后,才能进行下一步操作

 

具体操作步骤如下:
  1. 声明一个最大值为20,初始值为20的信号量s1和一个最大值为1,初始值为0的信号量s2,以及一个任务计数器count。
  2. 将需要线程池操作的任务数赋给count。 
  3. 在调用线程池的循环中,调用s1的WaitOne方法,在线程的具体操作执行完毕后调用s1的Release方法,并且使用Interlocked的Decrement方法将任务数count减1,并且判断count是否等于0,如果count等于0,调用s2的Release方法。
  4. 最后在调用线程池的循环结束之后,调用s2的WaitOne方法。
运行截图如下:


具体代码如下:

 using System;

using System.Threading;
using System.Collections.Generic;

public class UseSemaphore
{
    
private static readonly Semaphore s1 = new Semaphore(3,3);
    
private static readonly Semaphore s2 = new Semaphore(0,1);
    
private const int TaskCount = 10;
    
private static int count;

    
public static void Main()
    {
        Console.WriteLine(
"MainThread Start");
        count 
= TaskCount;
        
for(int i = 0; i < TaskCount; ++i)
        {
            s1.WaitOne();
            ThreadPool.QueueUserWorkItem(Process, 
null);
        }
        s2.WaitOne();
        Console.WriteLine(
"MainThread");
        Console.ReadKey();
    }
    
    
private static void Process(object obj)
    {
        Console.WriteLine(
"ThreadPool {0} Start", Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(
100);
        Console.WriteLine(
"ThreadPool {0} Stop", Thread.CurrentThread.ManagedThreadId);
        s1.Release();
        Interlocked.Decrement(
ref count);
        
if(count == 0)
        {
            Console.WriteLine(
"s2 Release");
            s2.Release();
        }
    }
}
posted @ 2011-05-21 11:30  说不得  阅读(2900)  评论(7编辑  收藏  举报