信号量(semaphore)不过是由内核维护的 int32变量而已,(说通俗点就是好比一个线程容器里面允许执行的线程数,0计数就是允许执行的0个线程数,1就是允许执行的1个线程数,2就是允许执行的2个线程数,等等一次类推。。。。。。,0就是当前执行的线程数占满了容器没空余的了)

    当信号量为0时,在信号量上等待的线程会全部阻塞;

    当信号量大于0时,就解除阻塞。

  在一个信号量上等待的一个线程解除阻塞时,内核自动从信号量的计数中减1,线程运行完后调用Release,计数就加1。信号量还关联了一个最大的Int32值,当前计数绝不允许超过最大计数。下面展示了semaphore类的样子: 

  1.  
  1. public sealed class Semaphore :WaitHandle{
  2. //初始化信号量:初始请求数为initialCount,最大请求数为maximumCount
  3. public Semaphore(Int32 initialCount,Int32 maximumCount);
  4. public Int32 Release();//调用Release(1);返回上一个计数
  5. public Int32 Release(Int32 releaseCount);//返回上一个计数
  6. }
  1. initialCount:就是初始化信号量时,解除阻塞的线程数。
  2.  
  3. maximumCount:就是信号量允许执行的最大线程数。
  1.  

  一个自动重置事件在行为上和最大计数为1的信号量非常相似。两者的区别在于,可以在一个自动重置事件上连续多次调用Set,同时仍然只有一个线程解除阻塞。相反,在一个信号量上连续多次调用Release,会使它的内部计数一直递增,这可能解除大量线程的阻塞。如果在一个信号量上多次调用Release,会导致它的计数超过最大计数,这是Release会抛出一个SemaphoreFullException.

  请看MSDN中的一个例子:

  

  1. using System;
  2. using System.Threading;
  3.  
  4. public class Example
  5. {
  6. // A semaphore that simulates a limited resource pool.
  7. //
  8. private static Semaphore _pool;
  9.  
  10. // A padding interval to make the output more orderly.
  11. private static int _padding;
  12.  
  13. public static void Main()
  14. {
  15. // Create a semaphore that can satisfy up to three
  16. // concurrent requests. Use an initial count of zero,
  17. // so that the entire semaphore count is initially
  18. // owned by the main program thread.
  19. //初始化时允许解除的阻塞线程数量为0,最大的执行线程数为3,所以在第执行完第44行代码之前,开启的子线程中的代码都不会执行,如果注释掉第45行代码,这5个子线程都不会执行,如果改成:new Semaphore(1,3)初始化时允许解除的阻塞线程数量为1,最大执行的线程数为3,所以在执行完31行代码后会有一个子线程在运行的,如果注释掉第45行代码,就会只有一个信号量慢慢的运行完这5个子线程
  20. _pool = new Semaphore(, );
  21.  
  22. // Create and start five numbered threads.
  23. //
  24. for (int i = ; i <= ; i++)
  25. {
  26. Thread t = new Thread(new ParameterizedThreadStart(Worker));
  27.  
  28. // Start the thread, passing the number.
  29. //
  30. t.Start(i);
  31. }
  32.  
  33. // Wait for half a second, to allow all the
  34. // threads to start and to block on the semaphore.
  35. //
  36. Thread.Sleep();
  37.  
  38. // The main thread starts out holding the entire
  39. // semaphore count. Calling Release(3) brings the
  40. // semaphore count back to its maximum value, and
  41. // allows the waiting threads to enter the semaphore,
  42. // up to three at a time.
  43. //
  44. Console.WriteLine("Main thread calls Release(3).");
  45. _pool.Release();//此句代码的通俗意思就是重新再增加3个可以执行的线程,如果初始化new semaphore(1,5)运行完这代代码就是1+3=4个线程数解除阻塞了,如果初始化为new semaphore(0,5)运行完这段代码就是0+3=3个线程数解除阻塞了。
  46. //Console.WriteLine("_pool {0}", _pool.Release());
  47. //Console.WriteLine("_pool {0}", _pool.Release());
  48. //Console.WriteLine("_pool {0}", _pool.Release());
  49. //Console.WriteLine("_pool {0}", _pool.Release());
  50. //Console.WriteLine("_pool {0}", _pool.Release());
  51.  
  52. Console.WriteLine("Main thread exits.");
  53.  
  54. // Thread.Sleep(5000);
  55. // Console.WriteLine("_pool {0}", _pool.Release());
  56.  
  57. Console.ReadLine();
  58. }
  59.  
  60. private static void Worker(object num)
  61. {
  62. // Each worker thread begins by requesting the
  63. // semaphore.
  64. Console.WriteLine("Thread {0} begins " +
  65. "and waits for the semaphore.", num);
  66. _pool.WaitOne();
  67.  
  68. // A padding interval to make the output more orderly.
  69. int padding = Interlocked.Add(ref _padding, );
  70.  
  71. Console.WriteLine("Thread {0} enters the semaphore.", num);
  72.  
  73. // The thread's "work" consists of sleeping for
  74. // about a second. Each thread "works" a little
  75. // longer, just to make the output more orderly.
  76. //模拟阻塞线程
  77. Thread.Sleep(1000 + padding);
  78.  
  79. Console.WriteLine("Thread {0} releases the semaphore.", num);
  80. Console.WriteLine("Thread {0} previous semaphore count: {1}",
  81. num, _pool.Release());
  82. }
  83. }
    运行的其中之一的一个结果为:
  1. Thread begins and waits for the semaphore.
  2. Thread begins and waits for the semaphore.
  3. Thread begins and waits for the semaphore.
  4. Thread begins and waits for the semaphore.
  5. Thread begins and waits for the semaphore.
  6. Main thread calls Release().
  7. Thread enters the semaphore.
  8. Thread releases the semaphore.
  9. Thread previous semaphore count:
  10. Thread enters the semaphore.
  11. Thread releases the semaphore.
  12. Thread previous semaphore count:
  13. Thread enters the semaphore.
  14. Thread releases the semaphore.
  15. Thread previous semaphore count:
  16. Main thread exits.
  17. Thread enters the semaphore.
  18. Thread releases the semaphore.
  19. Thread previous semaphore count: 1 //执行这段代码前。信号量(semaphore)中还有两个线程在执行(当前运行运行的线程和下面还没运行完的一个线程,所以剩余1个线程的信号量(semaphore)可以执行.
  20. Thread enters the semaphore.
  21. Thread releases the semaphore.
  22. Thread previous semaphore count: 2 //执行这段代码前。信号量(semaphore)中有2个空闲的位置,可以执行线程了。

 这只是自己的理解,不正确的望各位大侠们指教。。。。。。。。。。。。。。。

基元线程同步构造之信号量(Semaphore)的更多相关文章

  1. [.net]基元线程同步构造

    /* 基元线程同步构造 用户模式构造: 易变构造(Volatile Construct) 互锁构造(Interlocked Construct):自旋锁(Spinlock) 乐观锁(Optimisti ...

  2. 基元线程同步构造之waithandle中 waitone使用

    在使用基元线程同步构造中waithandle中waitone方法的讲解: 调用waithandle的waitone方法阻止当前线程(提前是其状态为Nonsignaled,即红灯),直到当前的 Wait ...

  3. 【C#进阶系列】28 基元线程同步构造

    多个线程同时访问共享数据时,线程同步能防止数据损坏.之所以要强调同时,是因为线程同步问题实际上就是计时问题. 不需要线程同步是最理想的情况,因为线程同步一般很繁琐,涉及到线程同步锁的获取和释放,容易遗 ...

  4. Clr Via C#读书笔记----基元线程同步构造

    线程文章:http://www.cnblogs.com/edisonchou/p/4848131.html 重点在于多个线程同时访问,保持线程的同步. 线程同步的问题: 1,线程同步比较繁琐,而且容易 ...

  5. 基元线程同步构造之 Mutes(互斥体)

    互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex)). 互斥体禁止多个线程同时进入受保护的代码“临界区”(critical section). 因 ...

  6. CLR via C# I/O基元线程同步构造

    1. 分为用户模式构造和内核模式构造 2. 用户模式构造 a.易失构造 在一个简单数据类型的变量上执行原子性读或写操作 VolaileWrite 强制address中的值在调用时写入,除此之外,按照源 ...

  7. 基元线程同步构造 AutoResetEvent和ManualResetEvent 线程同步

    在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别.ManualResetEvent和AutoResetEvent都 ...

  8. 【C#进阶系列】29 混合线程同步构造

    上一章讲了基元线程同步构造,而其它的线程同步构造都是基于这些基元线程同步构造的,并且一般都合并了用户模式和内核模式构造,我们称之为混合线程同步构造. 在没有线程竞争时,混合线程提供了基于用户模式构造所 ...

  9. 【C#】C#线程_基元线程的同步构造

    目录结构: contents structure [+] 简介 为什么需要使用线程同步 线程同步的缺点 基元线程同步 什么是基元线程 基元用户模式构造和内核模式构造的比较 用户模式构造 易变构造(Vo ...

随机推荐

  1. golang fmt用法举例

    下标与参数的对应 例子如下: package main import ( "fmt" ) func main() { num := 10 fmt.Printf("num: ...

  2. 【jmeter】jmeter测试手机app的服务器压力

    具体步骤: 1.电脑启动jmeter 2.jmeter在测试计划新建线程组. 3.在工作台新建http代理服务器 4.配置HTTP代理服务器 5.设置IE代理到本地 6.手机wifi设置代理连接到PC ...

  3. fckeditor 配置

    因为下载下来的压缩包里面有包含很多在我们使用时,用不到的,不删除也行.看个人喜好下面以PHP为例,进行程序瘦身 删除所有”_”开头的文件和文件夹   删除FCKeditor的目录下:   fckedi ...

  4. VS2008项目使用VS2015打开时,出现错误: error CS1012: Too many characters in character literal

    VS2008项目使用VS2015打开时,出现错误: error CS1012: Too many characters in character literal ------------------- ...

  5. g++编译后中文显示乱码解决方案

    环境:Windows 10 专业版 GCC版本:5.3.0 测试代码: #include <iostream> using namespace std; int main(int argc ...

  6. 1114 Family Property (25 分)

    1114 Family Property (25 分) This time, you are supposed to help us collect the data for family-owned ...

  7. 1053 Path of Equal Weight (30 分)

    Given a non-empty tree with root R, and with weight W​i​​ assigned to each tree node T​i​​. The weig ...

  8. CentOS 6.4 添加永久静态路由所有方法汇总(原创)

    转摘,原文章地址:http://blog.sina.com.cn/s/blog_828e50020101ern5.html 查看路由的命令route -n CentOS添加永久静态路由 在使用双网卡, ...

  9. SpringBoot入门篇--Thymeleaf引擎模板的基本使用方法

    我们在使用SpringBoot框架的时候在前面已经介绍了Thymelea引擎模板,因为SpringBoot对JSP惨不忍睹的支持.那我们在使用引擎模板对前端页面进行渲染能够返回的情况下我们怎么才能在静 ...

  10. Eclipse变量名自动补全问题 自定义上屏按键为TAB

    Eclipse空格等号等都可以上屏,这样有时候输入变量名再按空格就会自动补全,非常讨厌.那么怎么办呢? 1.首先你的Eclipse需要装有 Eclipse plug-in development en ...