前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Semaphore 信号量

Semaphore 信号量

作者头像
leon公众号精选
发布2022-04-27 16:09:03
4270
发布2022-04-27 16:09:03
举报

Semaphore

c#信号量Semaphore只允许有限数量的线程进入临界区。信号量主要用于资源有限,我们必须限制使用线程的数量的场景。

代码语言:javascript
复制
Semaphore semaphoreObject = new Semaphore(initialCount: 0, maximumCount: 5);

信号量的工作原理

信号量是存储在操作系统资源中的Int32变量。当使用int类型参数进行初始化信号量对象时,这个参数的数字值限制了可以进入临界区的线程数。 当线程进入临界区时,它将Int32变量的值减小为1,当线程从临界区退出时,它将Int32变量的值增加为1。 当Int32变量为0时,没有线程可以进入临界区。 下面是c#信号量初始化的语法。

代码语言:javascript
复制
  Semaphore semaphoreObject = new Semaphore(initialCount: 0, maximumCount:

我们用两个参数初始化Semaphore :

  • 初始计数InitialCount
  • 最大计数MaximumCount

最大计数定义了可以进入临界区的最大线程数。初始计数设置 Int32 变量值。例如,如果我们设置最大计数为 3,初始计数为 0。这意味着 3 个线程已经在临界区。如果我们将最大计数设置为 3,初始计数设置为 3,则意味着最多可以有 3 个线程进入临界区,并且临界区中当前没有线程.

在多个进程之间使用信号量

或者 semaphore 有另一个构造函数,它接受额外的字符串作为参数。该字符串参数是一个唯一的字符串,用于在多个进程之间使用信号量

以下是创建信号量的用法。

代码语言:javascript
复制
Semaphore semaphoreObject = new Semaphore(initialCount: 0, maximumCount: 5, name: "MyUniqueNameApp");

WaitOne 方法

线程可以通过 WaitOne 方法进入临界区。他们在信号量对象上调用了 WaitOne 方法。如果信号量维护的 Int32 变量大于 0,则允许调用线程进入。

以下是调用WaitOne 的方式。

代码语言:javascript
复制
semaphoreObject.WaitOne();

在信号量 WaitOne 方法的另一个重载中,我们可以通过时间间隔,线程可以等待从信号量获取信号。如果线程在指定的时间内没有收到信号,则返回 false 值

代码语言:javascript
复制
bool isSignalled = semaphoreObject.WaitOne(TimeSpan.FromSeconds(4));

在上面的例子中,如果调用线程在指定的 4 秒内没有收到信号,则返回 false。如果它接收到信号,则返回真。

Release 方法

当一个线程从临界区退出时,它必须调用 Release 方法来增加信号量对象维护的计数器。进而允许等待线程进入临界区

代码语言:javascript
复制
semaphoreObject.Release();

默认情况下,Release 方法只将计数器加 1。这意味着只有一个线程从临界区退出。我们还可以向 Release 方法传递一个参数来定义实际退出的线程数。

代码语言:javascript
复制
semaphoreObject.Release(3);

在上面的代码中,我们将 3 传递给 Release 方法。这将通知信号量对象实际上有 3 个线程从临界区退出。所以信号量对象将计数器增加 3。

Semaphore 示例

在下面的示例中显示了如何将信号量对象与Console一起使用。要求限制可以同时使用 Printer 对象的线程数。为此,我们使用最大计数为 3 的信号量对象。

代码语言:javascript
复制
class Program
{
    static void Main(string[] args)
    {
        Semaphore semaphoreObject = new Semaphore(initialCount: 3, maximumCount: 3, name: "PrinterApp");
        Printer printerObject = new Printer();
 
        for (int i = 0; i < 20; ++i)
        {
            int j = i;
            Task.Factory.StartNew(() =>
                {
                    semaphoreObject.WaitOne();
                    printerObject.Print(j);
                    semaphoreObject.Release();
                });
        }
        Console.ReadLine();
    }
}
 
class Printer
{
    public void Print(int documentToPrint)
    {
        Console.WriteLine("Printing document: " + documentToPrint);
        Thread.Sleep(TimeSpan.FromSeconds(5));
    }
}

初始化信号量对象,并设置了初始化数和最大数,并给出唯一名称“PrinterApp”。以从 0 到 20 的运行开始 for 循环。使用 TaskFactory 启动线程

每个线程在使用Printer 对象之前都会调用semaphore 对象的WaitOne() 方法。这将限制使用Printer对象的线程数。使用Printer对象后,每个线程调用 Release() 方法来增加信号量的计数器以使更多线程可进入临界区

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师高级俱乐部 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Semaphore
    • 信号量的工作原理
      • Semaphore 示例
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档