应用程序中有多少个线程?如何设置信号量的个数?
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) 可用。然后,由于不同的休眠时间,方法调用输出向您展示了信号量是如何工作的。
信号量的意思是指定一次可以进入临界区的线程数。
以下代码设置计数为 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) 可用。然后,由于不同的休眠时间,方法调用输出向您展示了信号量是如何工作的。