应用程序中有多少个线程?如何设置信号量的个数?

How many threads in the application? How to set the count of semaphore?

信号量的意思是指定一次可以进入临界区的线程数。

以下代码设置计数为 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个线程共存。只有两个线程。

我是不是误会了什么?

您使用 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) 可用。然后,由于不同的休眠时间,方法调用输出向您展示了信号量是如何工作的。