基元线程同步构造之信号量(Semaphore)
信号量(semaphore)不过是由内核维护的 int32变量而已,(说通俗点就是好比一个线程容器里面允许执行的线程数,0计数就是允许执行的0个线程数,1就是允许执行的1个线程数,2就是允许执行的2个线程数,等等一次类推。。。。。。,0就是当前执行的线程数占满了容器没空余的了)。
当信号量为0时,在信号量上等待的线程会全部阻塞;
当信号量大于0时,就解除阻塞。
在一个信号量上等待的一个线程解除阻塞时,内核自动从信号量的计数中减1,线程运行完后调用Release,计数就加1。信号量还关联了一个最大的Int32值,当前计数绝不允许超过最大计数。下面展示了semaphore类的样子:
public sealed class Semaphore :WaitHandle{
//初始化信号量:初始请求数为initialCount,最大请求数为maximumCount
public Semaphore(Int32 initialCount,Int32 maximumCount);
public Int32 Release();//调用Release(1);返回上一个计数
public Int32 Release(Int32 releaseCount);//返回上一个计数
}
initialCount:就是初始化信号量时,解除阻塞的线程数。 maximumCount:就是信号量允许执行的最大线程数。
一个自动重置事件在行为上和最大计数为1的信号量非常相似。两者的区别在于,可以在一个自动重置事件上连续多次调用Set,同时仍然只有一个线程解除阻塞。相反,在一个信号量上连续多次调用Release,会使它的内部计数一直递增,这可能解除大量线程的阻塞。如果在一个信号量上多次调用Release,会导致它的计数超过最大计数,这是Release会抛出一个SemaphoreFullException.
请看MSDN中的一个例子:
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.
//初始化时允许解除的阻塞线程数量为0,最大的执行线程数为3,所以在第执行完第44行代码之前,开启的子线程中的代码都不会执行,如果注释掉第45行代码,这5个子线程都不会执行,如果改成:new Semaphore(1,3)初始化时允许解除的阻塞线程数量为1,最大执行的线程数为3,所以在执行完31行代码后会有一个子线程在运行的,如果注释掉第45行代码,就会只有一个信号量慢慢的运行完这5个子线程
_pool = new Semaphore(, ); // Create and start five numbered threads.
//
for (int i = ; i <= ; 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(); // 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个可以执行的线程,如果初始化new semaphore(1,5)运行完这代代码就是1+3=4个线程数解除阻塞了,如果初始化为new semaphore(0,5)运行完这段代码就是0+3=3个线程数解除阻塞了。
//Console.WriteLine("_pool {0}", _pool.Release());
//Console.WriteLine("_pool {0}", _pool.Release());
//Console.WriteLine("_pool {0}", _pool.Release());
//Console.WriteLine("_pool {0}", _pool.Release());
//Console.WriteLine("_pool {0}", _pool.Release()); Console.WriteLine("Main thread exits."); // Thread.Sleep(5000);
// Console.WriteLine("_pool {0}", _pool.Release()); Console.ReadLine();
} 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, ); 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());
}
}
运行的其中之一的一个结果为:
Thread begins and waits for the semaphore.
Thread begins and waits for the semaphore.
Thread begins and waits for the semaphore.
Thread begins and waits for the semaphore.
Thread begins and waits for the semaphore.
Main thread calls Release().
Thread enters the semaphore.
Thread releases the semaphore.
Thread previous semaphore count:
Thread enters the semaphore.
Thread releases the semaphore.
Thread previous semaphore count:
Thread enters the semaphore.
Thread releases the semaphore.
Thread previous semaphore count:
Main thread exits.
Thread enters the semaphore.
Thread releases the semaphore.
Thread previous semaphore count: 1 //执行这段代码前。信号量(semaphore)中还有两个线程在执行(当前运行运行的线程和下面还没运行完的一个线程,所以剩余1个线程的信号量(semaphore)可以执行.
Thread enters the semaphore.
Thread releases the semaphore.
Thread previous semaphore count: 2 //执行这段代码前。信号量(semaphore)中有2个空闲的位置,可以执行线程了。
这只是自己的理解,不正确的望各位大侠们指教。。。。。。。。。。。。。。。
基元线程同步构造之信号量(Semaphore)的更多相关文章
- [.net]基元线程同步构造
/* 基元线程同步构造 用户模式构造: 易变构造(Volatile Construct) 互锁构造(Interlocked Construct):自旋锁(Spinlock) 乐观锁(Optimisti ...
- 基元线程同步构造之waithandle中 waitone使用
在使用基元线程同步构造中waithandle中waitone方法的讲解: 调用waithandle的waitone方法阻止当前线程(提前是其状态为Nonsignaled,即红灯),直到当前的 Wait ...
- 【C#进阶系列】28 基元线程同步构造
多个线程同时访问共享数据时,线程同步能防止数据损坏.之所以要强调同时,是因为线程同步问题实际上就是计时问题. 不需要线程同步是最理想的情况,因为线程同步一般很繁琐,涉及到线程同步锁的获取和释放,容易遗 ...
- Clr Via C#读书笔记----基元线程同步构造
线程文章:http://www.cnblogs.com/edisonchou/p/4848131.html 重点在于多个线程同时访问,保持线程的同步. 线程同步的问题: 1,线程同步比较繁琐,而且容易 ...
- 基元线程同步构造之 Mutes(互斥体)
互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex)). 互斥体禁止多个线程同时进入受保护的代码“临界区”(critical section). 因 ...
- CLR via C# I/O基元线程同步构造
1. 分为用户模式构造和内核模式构造 2. 用户模式构造 a.易失构造 在一个简单数据类型的变量上执行原子性读或写操作 VolaileWrite 强制address中的值在调用时写入,除此之外,按照源 ...
- 基元线程同步构造 AutoResetEvent和ManualResetEvent 线程同步
在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别.ManualResetEvent和AutoResetEvent都 ...
- 【C#进阶系列】29 混合线程同步构造
上一章讲了基元线程同步构造,而其它的线程同步构造都是基于这些基元线程同步构造的,并且一般都合并了用户模式和内核模式构造,我们称之为混合线程同步构造. 在没有线程竞争时,混合线程提供了基于用户模式构造所 ...
- 【C#】C#线程_基元线程的同步构造
目录结构: contents structure [+] 简介 为什么需要使用线程同步 线程同步的缺点 基元线程同步 什么是基元线程 基元用户模式构造和内核模式构造的比较 用户模式构造 易变构造(Vo ...
随机推荐
- android 更新listview 其中一行的数据显示
private void updateView(int index){ View v = yourListView.getChildAt(index - yourListView.getFirstVi ...
- Kibana安装及使用
1.Kibana介绍Kibana是一个基于浏览器页面的Elasticsearch前端展示工具.Kibana全部使用HTML语言和Javascript编写的. 2.安装配置Kibana下载地址:http ...
- Parquet列式存储格式
Parquet是面向分析型业务的列式存储格式,由Twitter和Cloudera合作开发,2015年5月从Apache的孵化器里毕业成为Apache顶级项目,最新的版本是1.8.0. 列式存储 列式存 ...
- js中级总结
this问题: this是JavaScript的关键字 用途:指向某一个对象 如何判断this的指向 函数内:两种情况:1.以函数形式调用(不带 . 指向window ) 2.以方法形式调用 ...
- eclipse在线安装jd反编译插件
eclipse在线安装jd反编译插件地址 http://jd.benow.ca/jd-eclipse/update
- MFC~~~~~~edit_control 和 静态文本框设置透明和字体设置
一 字体设置比较简单~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 .在 testdlg.h(假设工程名字为test)中 设置一个 public 的 ...
- 第3章 文件I/O(2)_文件I/O系统调用及文件描述符
2. 文件I/O系统调用及文件描述符 2.1 文件I/O系统调用 (1)主要函数 函数 功能 函数 功能 open() 打开文件 read() 读取文件 creat() 创建文件 write() 写入 ...
- Java与C++语法的区别
1. 注释可以在Java程序中起到文档标记的作用 类文档标记: 1)@version 2)@author 3)@param 4)@return 5)@exception 2. Java的字符占两个字节 ...
- C++并发编程 02 数据共享
在<C++并发编程实战>这本书中第3章主要将的是多线程之间的数据共享同步问题.在多线程之间需要进行数据同步的主要是条件竞争. 1 std::lock_guard<std::mute ...
- TensorFlow系列专题(一):机器学习基础