2017-08-11 23 views
0

信号量意味着指定一次可以进入关键区域的线程数量。应用程序中有多少个线程?如何设置信号量?

设置计数下面的代码是5

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace ConsoleApp1 
{ 
    class Program 
    { 
     static Semaphore semaphore = new Semaphore(5, 5); 
     static void Main(string[] args) 
     { 
      Task.Factory.StartNew(() => 
      { 
       for (int i = 1; i <= 15; ++i) 
       { 
        PrintSomething(i); 
        if (i % 5 == 0) 
        { 
         Thread.Sleep(2000); 
        } 
       } 
      }); 
      Console.ReadLine(); 
     } 

     public static void PrintSomething(int number) 
     { 
      semaphore.WaitOne(); 
      Console.WriteLine(number); 
      semaphore.Release(); 
     } 
    } 
} 

每一次我们可以有5个线程在任何时间运行的手段。打印结果验证该点。

我的问题是,我没有看到这么多的线程运行。说15个线程运行,每次只能让5个线程共存。只有两个线程。 thread

我误解了一些东西?

+0

请将您的标题改为具有意义的东西。 * Semaphore *和* multithreading *都在标签中,因此它们在标题中没有多余地使用,并且删除它们不会留下任何有意义的内容。您的标题应该以对未来的读者在搜索结果列表中看到它有用的方式解释您遇到的问题或您要问的问题。 –

+1

您可能会安排线程池的工作,而不是专用线程。 – vcsjones

+0

系统给你一个初始线程。您创建了一个工作线程来运行该任务。这使得两个。 –

回答

0

您使用Task.Factory.StartNew()开始一个额外的线程,就是这样。在那个线程中,你依次调用PrintSomething()方法,所以你的线程输出截图是正确的。

如下更改代码:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace SempahoreTest1 
{ 
    class Program 
    { 
    static Semaphore semaphore = new Semaphore(5, 5); 

    static void Main(string[] args) 
    { 
     for (int i = 1; i <= 15; ++i) 
     { 
     Task.Factory.StartNew((state) => 
     { 
      int number = (int)state; 

      PrintSomething(number); 
      if (i % 5 == 0) 
      { 
      Thread.Sleep(2000); 
      } 
     }, i); 
     } 
     Console.ReadLine(); 
    } 

    public static void PrintSomething(int number) 
    { 
     semaphore.WaitOne(); 
     try 
     { 
     Console.WriteLine("Thread: {0}, Number: {1}", Thread.CurrentThread.ManagedThreadId, number); 
     } 
     finally 
     { 
     semaphore.Release(); 
     } 
    } 
    } 
} 

更新:

一个更好的解释,如何旗语的作品,应该是:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace SempahoreTest1 
{ 
    class Program 
    { 
    static Semaphore semaphore = new Semaphore(5, 5); 
    static Random random = new Random(); 

    static void Main(string[] args) 
    { 
     Parallel.For(1, 16, PrintSomething); 

     Console.ReadLine(); 
    } 

    public static void PrintSomething(int number) 
    { 
     semaphore.WaitOne(); 
     try 
     { 
     Console.WriteLine("Thread: {0}, Number: {1}, Access granted", Thread.CurrentThread.ManagedThreadId, number); 
     // sleep to simulate long running method 
     Thread.Sleep(random.Next(1000, 5000)); 
     } 
     finally 
     { 
     semaphore.Release(); 
     Console.WriteLine("Thread: {0}, Number: {1}, Semaphore released", Thread.CurrentThread.ManagedThreadId, number); 
     } 
    } 
    } 
} 

并行循环从调用PrintSomething()不同的线程。每次调用信号量计数器都会减少,直到达到0. PrintSomething()的下一个调用块将在semaphore.WaitOne()上阻塞,直到第一次调用semaphore.Release(),这会再次增加信号量计数器。等等...... 前5次调用非常快,因为最大信号计数(5)可用。然后,由于不同的睡眠时间,方法调用输出会显示信号灯的工作方式。

+0

得到的问题是的。使用该示例的[链接](http://dotnetpattern.com/multi-threading-interview-questions)是否错误地解释了这个概念?并且在链接中,打印结果每次都输出5。这是令人困惑的,因为我认为有超过5个线程。 – Bigeyes

+0

@Bigeyes:这个例子是完全错误的。你可以注释掉semaphore.WaitOne()和semaphore.Release(),输出相同。这是因为来自同一个线程的循环中的顺序调用。它增加5倍,然后等待2秒等等。 – KBO

相关问题