我使用信号量错了吗?

问题描述:

我需要使用信号量并行执行一些任务。我试试这个:我使用信号量错了吗?

Semaphore sema = new Semaphore(2,2); 
Thread[] Threads = new Thread[5]; 
for (int k = 0; k < 5; k++) { 
    sema.WaitOne(); 
    Console.WriteLine((k + 1) + " started"); 
    Threads[k] = new Thread(ThreadMethod1); 
    Threads[k].Start(k + 1); 
    sema.Release(); 
} 

static void ThreadMethod1(object id) { 
    Thread.Sleep(50); 
    Console.WriteLine(id + " completed"); 
} 

输出的样子:

1 started 
2 started 
3 started 
4 started 
5 started 
1 completed 
2 completed 
4 completed 
3 completed 
5 completed 

是不是应该旗语让只有2个线程来运行?我不明白或做错了什么?

+4

是的,但是您在每个周期的主线程中都要退出信号量,所以信号量总是处于非阻塞状态。 – xanatos 2015-02-24 09:55:24

您正在输入/退出“主”线程中的信号量。这是无用的,因为在每个“循环”中你都会进入和退出它。在这个修改的例子中,你在主线程中输入信号量,并在完成工作线程后退出它。

注意,我不得不把信号传递给工作线程(我用了Tuple,但其他方法都ok)

static void Main(string[] args) { 
    Semaphore sema = new Semaphore(2, 2); 

    Thread[] Threads = new Thread[5]; 
    for (int k = 0; k < 5; k++) { 
     sema.WaitOne(); 

     Console.WriteLine((k + 1) + " started"); 

     Threads[k] = new Thread(ThreadMethod1); 
     Threads[k].Start(Tuple.Create(k + 1, sema)); 
    } 
} 

static void ThreadMethod1(object tuple) { 
    Tuple<int, Semaphore> tuple2 = (Tuple<int, Semaphore>)tuple; 
    Thread.Sleep(50); 
    Console.WriteLine(tuple2.Item1 + " completed"); 
    tuple2.Item2.Release(); 
} 

你可以移动sema.WaitOne“内部” ThreadMethod1,但它会不同的是:所有的线程都会被创建,但会“等待”,每次只有2个线程会做“真正的工作”。正如所写,最多创建两个线程(并完成工作)

+1

看起来像我累了,想不到正确。谢谢! – InfernumDeus 2015-02-24 09:59:57

您只需将信号量的操作从主线程移动即可。对你的代码进行小修改就可以解决它。

public static Semaphore sema = new Semaphore(2, 2); 

static void Main(string[] args) 
{ 
    Thread[] Threads = new Thread[5]; 
    for (int k = 0; k < 5; k++) 
    { 
     Console.WriteLine((k + 1) + " started"); 
     Threads[k] = new Thread(ThreadMethod1); 
     Threads[k].Start(k + 1); 
    } 
} 

static void ThreadMethod1(object id) 
{ 
    sema.WaitOne(); 
    Thread.Sleep(1000); 
    Console.WriteLine(id + " completed"); 
    sema.Release(); 
}