博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
初次接触.Net下的信号量(semaphore)
阅读量:4630 次
发布时间:2019-06-09

本文共 3803 字,大约阅读时间需要 12 分钟。

什么是信号量(Semaphore)

    如果你已经了解信号量(Semaphore)的概念了,请跳过这一段。

    信号量(Semaphore)是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

    我们来看看一个停车场是怎样运作的。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这是如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。

    在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

    更进一步,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait等待)操作时,它要么通过然后将信号量减一,要么一自等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是应为加操作实际上是释放了由信号量守护的资源。(引自:)

 

NET Framework 类库

Semaphore 类

注意:此类在 .NET Framework 2.0 版中是新增的。

限制可同时访问某一资源或资源池的线程数。

命名空间:System.Threading

程序集:System(在 system.dll 中)

Note注意

应用于此类的 属性 (Attribute) 具有下面的 属性 (Property) 值: | 。

HostProtectionAttribute 不影响桌面应用程序(桌面应用程序一般通过双击图标,键入命令或在浏览器中输入 URL 启动)。有关更多信息,
请参见 HostProtectionAttribute 类或 。

使用 Semaphore 类可控制对资源池的访问。线程通过调用 方法(从 类继承)进入信号量,并通过调用 方法释放信号量。

信号量的计数在每次线程进入信号量时减小,在线程释放信号量时增加。当计数为零时,后面的请求将被阻塞,直到有其他线程释放信号量。当所有的线程都已释放信号量时,计数达到创建信号量时所指定的最大值。

被阻止的线程并不一定按特定的顺序(如 FIFO 或 LIFO)进入信号量。

线程可通过重复调用 WaitOne 方法多次进入信号量。为释放这些入口中的部分或全部,线程可多次调用无参数的 方法重载,也可以调用 方法重载来指定要释放的入口数。

Semaphore 类不对 WaitOneRelease 调用强制线程标识。程序员负责确保线程释放信号量的次数不能太多。例如,假定信号量的最大计数为 2,并且线程 A 和线程 B 同时进入信号量。如果线程 B 中的编程错误导致它两次调用 Release,则两次调用都成功。这样,信号量的计数已满,当线程 A 最终调用 Release 时便会引发 。

信号量分为两种类型:局部信号量和已命名的系统信号量。如果您使用接受名称的构造函数创建 Semaphore 对象,则该对象与具有该名称的操作系统信号量关联。已命名的系统信号量在整个操作系统中都可见,可用于同步进程活动。您可以创建多个 Semaphore 对象来表示同一个已命名的系统信号量,也可以使用 方法打开现有的已命名系统信号量。

局部信号量仅存在于您的进程内。您的进程中任何引用局部 Semaphore 对象的线程都可以使用它。每个 Semaphore 对象都是一个单独的局部信号量。

下面的代码示例创建一个最大计数为 3、初始计数为 0 的信号量。该示例启动五个线程,这些线程阻止该信号量的等待。主线程使用 Release(Int32) 方法重载,以便将信号量计数增加为其最大值,从而允许三个线程进入该信号量。每个线程都使用 方法等待一秒钟以便模拟工作,然后调用 Release 方法重载以释放信号量。每次释放信号量时,都显示前一个信号量计数。控制台消息对信号量的使用进行跟踪。每个线程的模拟工作间隔都稍有增加,以使输出更为易读。

C#
using System;
using System.Threading;
public
class Example
{
   
// A semaphore that simulates a limited resource pool.
   
//
   
private
static Semaphore _pool;
   
// A padding interval to make the output more orderly.
   
private
static
int _padding;
   
public
static
void Main()
    {
       
// Create a semaphore that can satisfy up to three
       
// concurrent requests. Use an initial count of zero,
       
// so that the entire semaphore count is initially
       
// owned by the main program thread.
       
//
        _pool =
new Semaphore(0, 3);
       
// Create and start five numbered threads.
       
//
       
for(
int i = 1; i <= 5; i++)
        {
            Thread t =
new Thread(
new ParameterizedThreadStart(Worker));
           
// Start the thread, passing the number.
           
//
            t.Start(i);
        }
       
// Wait for half a second, to allow all the
       
// threads to start and to block on the semaphore.
       
//
        Thread.Sleep(500);
       
// The main thread starts out holding the entire
       
// semaphore count. Calling Release(3) brings the
       
// semaphore count back to its maximum value, and
       
// allows the waiting threads to enter the semaphore,
       
// up to three at a time.
       
//
        Console.WriteLine(
"Main thread calls Release(3).");
        _pool.Release(3);
        Console.WriteLine(
"Main thread exits.");
    }
   
private
static
void Worker(object num)
    {
       
// Each worker thread begins by requesting the
       
// semaphore.
        Console.WriteLine(
"Thread {0} begins " +
           
"and waits for the semaphore.", num);
        _pool.WaitOne();
       
// A padding interval to make the output more orderly.
       
int padding = Interlocked.Add(ref _padding, 100);
        Console.WriteLine(
"Thread {0} enters the semaphore.", num);
       
       
// The thread's "work" consists of sleeping for
       
// about a second. Each thread "works" a little
       
// longer, just to make the output more orderly.
       
//
        Thread.Sleep(1000 + padding);
        Console.WriteLine(
"Thread {0} releases the semaphore.", num);
        Console.WriteLine(
"Thread {0} previous semaphore count: {1}",
            num, _pool.Release());
    }
}

 

转载于:https://www.cnblogs.com/0633shj/archive/2008/11/21/1326531.html

你可能感兴趣的文章
learning to openstack concept
查看>>
Kindeditor学习中的那些坑
查看>>
Servlet
查看>>
一篇价值百万的文章:我为什么在22岁辞去年薪150万的工作?
查看>>
信息安全系统设计基础期末总结
查看>>
leetcode 203 Remove Linked List Elements
查看>>
TCP/IP 笔记 1.3 IP:网际协议
查看>>
HDU 1061 Rightmost Digit
查看>>
八种简易健康减肥瘦身法
查看>>
win7旗舰版下配置IIS服务器
查看>>
web开发基础
查看>>
java——逻辑运算符与(&和&&)或(|和||)
查看>>
iPhone App开发导航条(Navigation Bar)素材PSD下载
查看>>
jQuery中的事件机制深入浅出
查看>>
当前上下文中不存在viewbag
查看>>
Android拷贝工程不覆盖原工程的配置方法
查看>>
linux安装配置postgres及使用dblink
查看>>
ApacheBench(ab)使用详解
查看>>
SSH框架搭建笔记
查看>>
nginx语法
查看>>