2015-02-24 23 views
1

我需要使用信號量並行執行一些任務。我試試這個:我使用信號量錯了嗎?

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

回答

8

您正在輸入/退出「主」線程中的信號量。這是無用的,因爲在每個「循環」中你都會進入和退出它。在這個修改的例子中,你在主線程中輸入信號量,並在完成工作線程後退出它。

注意,我不得不把信號傳遞給工作線程(我用了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

0

您只需將信號量的操作從主線程移動即可。對你的代碼進行小修改就可以解決它。

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(); 
}