C# 并行编程 之 限制资源的并发访问 使用SemaphoreSlim
来源:互联网 发布:天猫魔盒看电视剧软件 编辑:程序博客网 时间:2024/06/18 14:49
概要
当多个任务或线程并行运行时,难以避免的对某些有限的资源进行并发的访问。可以考虑使用信号量来进行这方面的控制(System.Threading.Semaphore)是表示一个Windows内核的信号量对象。如果预计等待的时间较短,可以考虑使用SemaphoreSlim,它则带来的开销更小。
.NetFrameWork中的信号量通过跟踪进入和离开的任务或线程来协调对资源的访问。信号量需要知道资源的最大数量,当一个任务进入时,资源计数器会被减1,当计数器为0时,如果有任务访问资源,它会被阻塞,直到有任务离开为止。
示例程序: 10个任务并行访问3个资源
using System;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Diagnostics;namespace Sample5_8_semaphoreslim{ class Program { private static int _TaskNum = 10; private static Task[] _Tasks; private const int MAX_RESOURCE = 3; private const int RUN_LOOP = 10; private static SemaphoreSlim m_Semaphore; private static void Work1(int TaskID) { int i = 0; var sw = Stopwatch.StartNew(); var rnd = new Random(); while (i < RUN_LOOP) { Thread.Sleep(rnd.Next(200, 500)); Console.WriteLine("TASK " + TaskID + " REQUESTing {"); m_Semaphore.Wait(); try { Console.WriteLine("TASK " + TaskID + " WOrking ... ..." + i); sw.Restart(); Thread.Sleep(rnd.Next(200, 500)); } finally { Console.WriteLine("TASK " + TaskID + " REQUESTing }"); m_Semaphore.Release(); i++; } } } static void Main(string[] args) { _Tasks = new Task[_TaskNum]; m_Semaphore = new SemaphoreSlim(MAX_RESOURCE); int i = 0; for (i = 0; i < _TaskNum; i++) { _Tasks[i] = Task.Factory.StartNew((num) => { var taskid = (int)num; Work1(taskid); }, i); } var finalTask = Task.Factory.ContinueWhenAll(_Tasks, (tasks) => { Task.WaitAll(_Tasks); Console.WriteLine("=========================================================="); Console.WriteLine("All Phase is completed"); Console.WriteLine("=========================================================="); }); try { finalTask.Wait(); } catch (AggregateException aex) { Console.WriteLine("Task failed And Canceled" + aex.ToString()); } finally { m_Semaphore.Dispose(); } Console.ReadLine(); } }}
使用超时和取消
信号量当然不可能永久的阻塞在那里。信号量也提供了超时处理机制。方法是在Wait函数中传入一个超时等待时间 - Wait(int TIMEOUT)。当Wait返回值为false时表明它超时了。如果传入了 -1,则表示无限期的等待。
程序示例:注意其中的m_Semaphore.Release();已经被注释掉了,任务会等待1秒钟然后超时。
using System;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Diagnostics;namespace Sample5_8_semaphoreslim{ class Program { private static int _TaskNum = 10; private static Task[] _Tasks; private const int MAX_RESOURCE = 3; private const int RUN_LOOP = 10; private static SemaphoreSlim m_Semaphore; private static void Work1(int TaskID) { int i = 0; var sw = Stopwatch.StartNew(); var rnd = new Random(); while (i < RUN_LOOP) { Thread.Sleep(rnd.Next(200, 500)); Console.WriteLine("TASK " + TaskID + " REQUESTing {"); if (!m_Semaphore.Wait(1000)) { Console.WriteLine("TASK " + TaskID + " TIMEOUT!!!"); return; } try { Console.WriteLine("TASK " + TaskID + " WOrking ... ..." + i); sw.Restart(); Thread.Sleep(rnd.Next(2000, 5000)); } finally { Console.WriteLine("TASK " + TaskID + " REQUESTing }"); //m_Semaphore.Release(); i++; } } } static void Main(string[] args) { _Tasks = new Task[_TaskNum]; m_Semaphore = new SemaphoreSlim(MAX_RESOURCE); int i = 0; for (i = 0; i < _TaskNum; i++) { _Tasks[i] = Task.Factory.StartNew((num) => { var taskid = (int)num; Work1(taskid); }, i); } var finalTask = Task.Factory.ContinueWhenAll(_Tasks, (tasks) => { Task.WaitAll(_Tasks); Console.WriteLine("=========================================================="); Console.WriteLine("All Phase is completed"); Console.WriteLine("=========================================================="); }); try { finalTask.Wait(); } catch (AggregateException aex) { Console.WriteLine("Task failed And Canceled" + aex.ToString()); } finally { m_Semaphore.Dispose(); } Console.ReadLine(); } }}
跨进程或AppDomain的同步
如果需要有跨进程或AppDomain的同步时,可以考虑使用Semaphore。Semaphore是取得的Windows 内核的信号量,所以在整个系统中是有效的。
它主要的接口时 Release和WaitOne,使用的方式和SemaphoreSlim是一致的。
0 0
- C# 并行编程 之 限制资源的并发访问 使用SemaphoreSlim
- Java并发编程: 使用Semaphore限制资源并发访问的线程数
- C# 并行编程 之 Barrier的使用 - 通过屏障同步并发任务
- C# 并行编程 之 Barrier的使用 - 通过屏障同步并发任务
- C# 并行编程 之 互斥锁的使用
- C# 并行编程 之 Barrier的使用
- C#并行编程-并发集合
- C#并行编程-并发集合
- C# 并行编程 之 自旋锁的使用
- C# 并行编程 之 轻量级手动重置事件的使用
- C# 并行编程 之 ThreadPool的基本使用
- C# 并行编程 之 并发集合 (.Net Framework 4.0)
- C# 并行编程 之 并发集合 (.Net Framework 4.0)
- C# 并行编程 之 PLINQ 基本使用
- C# 并行编程 之 PLINQ并行度的指定 和 ForAll的使用
- (27)21.3.1 不正确的访问资源---Java编程思想之并发笔记
- 并发编程--资源并发访问信号量
- C# SemaphoreSlim 实现
- LeetCode Word Search II
- MyEclipse 使用手册
- IOS文件下载总结(一)
- mac下类似fildder的抓包工具charles安装与注册
- 【ThinkingInJava】48、java中Collection的各种操作
- C# 并行编程 之 限制资源的并发访问 使用SemaphoreSlim
- windows eclipse远程连接hadoop2.6
- 【ThinkingInJava】49、List的各种功能方法
- Apache Lucene 5.1.0 入门使用篇
- 【ThinkingInJava】50、使用特定的set
- 互联网精神
- 代立东-----使用MAT分析内存泄露【还有其他文章都是BigData优化方面的内容,很有用】
- OPENCV的学习:AdaptiveThreshold函数
- C++容器 java集合