C#高级编程五十八天----并行集合
并行集合
对于并行任务,与其相关紧密的就是对一些共享资源,数据结构的并行訪问.常常要做的就是对一些队列进行加锁-解锁,然后运行类似插入,删除等等相互排斥操作. .NET4提供了一些封装好的支持并行操作数据容器,能够降低并行编程的复杂程度.
并行集合的命名空间:System.Collections.Concurrent
并行容器:
ConcurrentQueue
ConcurrentStack
ConcurrentBag: 一个无序的数据结构集,当不考虑顺序时很实用.
BlockingCollection:与经典的堵塞队列数据结构类似
ConcurrentDictoinary
以上这些集合在某种程度上使用了无锁技术(CAS和内存屏蔽),与加相互排斥锁相比获得了性能的提升.可是在串行程序中,最好不要使用这些集合,他们必定会影响性能.
ConcurrentQueue使用方法与实例
其全然无锁,但当CAS面临资源竞争失败时可能会陷入自旋并重试操作.
Enqueue:在队尾插入元素
TryDequeue:尝试删除对头元素,并通过out參数返回
TryPeek:尝试将对头元素通过out參数返回,但不删除元素
案例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace 并行结合Queue
{
class Program
{
internal static ConcurrentQueue<int> _TestQueue;
class ThreadWork1 //生产者
{
public ThreadWork1()
{ }
public void run()
{
Console.WriteLine("ThreadWork1 run { ");
for (int i = 0; i < 100; i++)
{
Console.WriteLine("ThreadWork1 producer: "+i);
_TestQueue.Enqueue(i);
}
Console.WriteLine("ThreadWork1 run } ");
}
}
class ThreadWork2 //consumer
{
public ThreadWork2()
{ }
public void run()
{
int i = 0;
bool IsDequeue = false;
Console.WriteLine("ThreadWork2 run { ");
for (; ; )
{
IsDequeue = _TestQueue.TryDequeue(out i);
if (IsDequeue)
{
System.Console.WriteLine("ThreadWork2 consumer: " + i * i + " =====");
}
if (i==99)
{
break;
}
}
Console.WriteLine("ThreadWork2 run } ");
}
}
static void StartT1()
{
ThreadWork1 work1 = new ThreadWork1();
work1.run();
}
static void StartT2()
{
ThreadWork2 work2 = new ThreadWork2();
work2.run();
}
static void Main(string[] args)
{
Task t1 = new Task(() => StartT1());
Task t2 = new Task(() => StartT2());
_TestQueue = new ConcurrentQueue<int>();
Console.WriteLine("Sample 3-1 Main {");
Console.WriteLine("Main t1 t2 started {");
t1.Start();
t2.Start();
Console.WriteLine("Main t1 t2 started }");
Console.WriteLine("Main wait t1 t2 end {");
Task.WaitAll(t1, t2);
Console.WriteLine("Main wait t1 t2 end }");
Console.WriteLine("Sample 3-1 Main }");
Console.ReadKey();
}
}
}
ConcurrentStact
其全然无锁,但当CAS面临资源竞争失败时可能会陷入自旋并重试操作.
Push:向栈顶插入元素
TryPop:从栈顶弹出元素,而且通过out參数返回
TryPeek:返回栈顶元素,但不弹出
案例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace 并行结合Queue
{
class Program
{
internal static ConcurrentStack<int> _TestStack;
class ThreadWork1 //生产者
{
public ThreadWork1()
{ }
public void run()
{
Console.WriteLine("ThreadWork1 run { ");
for (int i = 0; i < 100; i++)
{
Console.WriteLine("ThreadWork1 producer: "+i);
_TestStack.Push(i);
}
Console.WriteLine("ThreadWork1 run } ");
}
}
class ThreadWork2 //consumer
{
public ThreadWork2()
{ }
public void run()
{
int i = 0;
bool IsDequeue = false;
Console.WriteLine("ThreadWork2 run { ");
for (; ; )
{
IsDequeue = _TestStack.TryPop(out i);
if (IsDequeue)
{
System.Console.WriteLine("ThreadWork2 consumer: " + i * i + " =====" + i);
}
if (i==99)
{
break;
}
}
Console.WriteLine("ThreadWork2 run } ");
}
}
static void StartT1()
{
ThreadWork1 work1 = new ThreadWork1();
work1.run();
}
static void StartT2()
{
ThreadWork2 work2 = new ThreadWork2();
work2.run();
}
static void Main(string[] args)
{
Task t1 = new Task(() => StartT1());
Task t2 = new Task(() => StartT2());
_TestStack = new ConcurrentStack<int>();
Console.WriteLine("Sample 4-1 Main {");
Console.WriteLine("Main t1 t2 started {");
t1.Start();
t2.Start();
Console.WriteLine("Main t1 t2 started }");
Console.WriteLine("Main wait t1 t2 end {");
Task.WaitAll(t1, t2);
Console.WriteLine("Main wait t1 t2 end }");
Console.WriteLine("Sample 4-1 Main }");
Console.ReadKey();
}
}
}
ConcurrentBag
一个无序的集合,程序能够向当中插入元素,或删除元素.
在同一个线程中向集合插入,删除元素效率非常高.
Add:向集合中插入元素
TryTake:从集合中取出元素并删除
TryPeek:从集合中取出元素,但不删除元素
案例:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 并行集合ConcurrentBag
{
class Program
{
internal static ConcurrentBag<int> _TestBag;
class ThreadWork1 //producer
{
public ThreadWork1()
{ }
public void run()
{
Console.WriteLine("Threadwork1 run { ");
for (int i = 0; i < 100; i++)
{
Console.WriteLine("ThreadWork1 producer: "+i);
_TestBag.Add(i);
}
Console.WriteLine("ThreadWork1 run } ");
}
}
class ThreadWork2//consumer
{
public ThreadWork2()
{ }
public void run()
{
bool IsDequeue = false;
Console.WriteLine("ThreadWork2 run { ");
for (int i = 0; i < 100; i++)
{
IsDequeue = _TestBag.TryTake(out i);
if (IsDequeue)
{
Console.WriteLine("ThreadWork2 consumer: " + i * i + "======" + i);
}
}
Console.WriteLine("ThreadWork2 run } ");
}
}
static void Start1()
{
ThreadWork1 work1 = new ThreadWork1();
work1.run();
}
static void Start2()
{
ThreadWork2 work2 = new ThreadWork2();
work2.run();
}
static void Main(string[] args)
{
Task t1 = new Task(() => Start1());
Task t2 = new Task(() => Start2());
_TestBag = new ConcurrentBag<int>();
t1.Start();
t2.Start();
Console.WriteLine("Main t1 t2 started }");
Console.WriteLine("Main wait t1 t2 end {");
Task.WaitAll(t1, t2);
Console.WriteLine("Main wait t1 t2 end }");
Console.WriteLine("Sample 4-3 Main }");
Console.ReadKey();
}
}
}
BlockingCollection
一个支持界限和堵塞的容器
Add:向容器中插入元素
TryTake:从容器中取出元素并删除
TryPeek:从容器中取出元素,但不删除
CompleteAdding:告诉容器,加入元素完毕.此时假设还想继续加入会发生异常.
IsCompleted:告诉消费者线程,产生者线程还在继续执行中,任务还未完毕.
案例:
程序中,消费者线程全然使用While(!__testCollection.IsCompleted)作为退出执行的推断条件.在Work1中,有两条语句被凝视了,当i为50时设置为CompleteAdding,但当继续向当中插入元素时,系统抛出异常,提示无法再继续插入.
案例:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 并行结合Collection
{
class Program
{
internal static BlockingCollection<int> _testBCollection;
class ThreadWork1 //producer
{
public ThreadWork1()
{ }
public void run()
{
Console.WriteLine("ThreadWork1 run { ");
for (int i = 0; i < 100; i++)
{
Console.WriteLine("ThreadWork1 producer: "+i);
_testBCollection.Add(i);
//当i为50时设置为CompleteAdding,但当继续向当中插入元素时,系统抛出异常,提示无法再继续插入.
//if (i==50)
//{
// _testBCollection.CompleteAdding();
//}
}
_testBCollection.CompleteAdding();
Console.WriteLine("ThreadWork1 run } ");
}
}
class ThreadWork2//consumer
{
public ThreadWork2()
{ }
public void run()
{
int i = 0;
bool IsDequeue = false;
Console.WriteLine("ThreadWork2 run { ");
while (!_testBCollection.IsCompleted)
{
//不明确这里为啥i会自己主动的++
//Console.WriteLine("i=================="+i);
IsDequeue = _testBCollection.TryTake(out i);
if (IsDequeue)
{
Console.WriteLine("ThreadWork2 consumer: "+i*i+"====="+i);
//i++;这句话不加还是会出现自己主动++的操作
}
}
}
}
static void StartT1()
{
ThreadWork1 work1 = new ThreadWork1();
work1.run();
}
static void StartT2()
{
ThreadWork2 work2 = new ThreadWork2();
work2.run();
}
static void Main(string[] args)
{
Task t1 = new Task(() => StartT1());
Task t2 = new Task(() => StartT2());
_testBCollection = new BlockingCollection<int>();
Console.WriteLine("Sample 4-4 Main {");
Console.WriteLine("Main t1 t2 started {");
t1.Start();
t2.Start();
Console.WriteLine("Main t1 t2 started }");
Console.WriteLine("Main wait t1 t2 end {");
Task.WaitAll(t1, t2);
Console.WriteLine("Main wait t1 t2 end }");
Console.WriteLine("Sample 4-4 Main }");
Console.ReadKey();
}
}
}
分析://_testBCollection.CompleteAdding();//这句话凝视掉work2陷入循环,无法退出
ConcurrentDictionary
对于读操作是全然无锁的,当非常多线程要改动数据时,它会使用细粒度的锁.
AddOrUpdate:假设键不存在,方法会在容器中加入新的键和值,假设存在,则更新现有的键和值
GetOrAdd:假设键不存在,方法会向容器中加入新的键和值,假设存在则返回现有的值,并不加入新值.
TryAdd:尝试在容器中加入新的键和值
TryGetValue:尝试依据指定的键获得值
TryUpdate:有条件的更新当前键所相应的值
TryRemove:尝试删除指定的键.
Getenumerator:返回一个可以遍历整个容器的枚举器.
案例:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 并行集合Dictionary
{
class Program
{
internal static ConcurrentDictionary<int, int> _TestDictionary;
class ThreadWork1//producer
{
public ThreadWork1()
{ }
public void run()
{
System.Console.WriteLine("ThreadWork1 run { ");
for (int i = 0; i < 100; i++)
{
System.Console.WriteLine("ThreadWork1 producer: " + i);
_TestDictionary.TryAdd(i, i);
}
System.Console.WriteLine("ThreadWork1 run } ");
}
}
class ThreadWork2//consumer
{
public ThreadWork2()
{ }
public void run()
{
bool IsOk = false;
Console.WriteLine("ThreadWork2 run { ");
int nCnt = 0,i=0,nValue=0;
while (nCnt<100)
{
IsOk = _TestDictionary.TryGetValue(i,out nValue);
if (IsOk)
{
Console.WriteLine("ThreadWork2 consumer: "+i*i+"====="+i);
nValue *= nValue;
nCnt++;
i++;
}
}
Console.WriteLine("ThreadWork2 run } ");
}
}
static void StartT1()
{
ThreadWork1 work1 = new ThreadWork1();
work1.run();
}
static void StartT2()
{
ThreadWork2 work2 = new ThreadWork2();
work2.run();
}
static void Main(string[] args)
{
Task t1 = new Task(() => StartT1());
Task t2 = new Task(() => StartT2());
bool bIsNext = true;
int nValue = 0;
_TestDictionary = new ConcurrentDictionary<int, int>();
Console.WriteLine("Sample 4-5 Main {");
Console.WriteLine("Main t1 t2 started {");
t1.Start();
t2.Start();
Console.WriteLine("Main t1 t2 started }");
Console.WriteLine("Main wait t1 t2 end {");
Task.WaitAll(t1, t2);
Console.WriteLine("Main wait t1 t2 end }");
foreach (var pair in _TestDictionary)
{
Console.WriteLine(pair.Key + " : " + pair.Value);
}
IEnumerator<KeyValuePair<int, int>> enumer = _TestDictionary.GetEnumerator();
while (bIsNext)
{
bIsNext = enumer.MoveNext();
Console.WriteLine("Key: " + enumer.Current.Key +" Value: " + enumer.Current.Value);
_TestDictionary.TryRemove(enumer.Current.Key, out nValue);
}
Console.WriteLine("\n\nDictionary Count: " + _TestDictionary.Count);
Console.WriteLine("Sample 4-5 Main }");
Console.ReadKey();
}
}
}
总结说明: .NET4包括的新命名空间System.Collection,Concurrent有几个线程安全的集合类.线程安全的集合可防止多个线程以相互冲突的方式訪问集合.
为了对集合进行线程安全的訪问,定义了IPriducerConsumerCollection<T>接口.这个接口中最重要的方法是TryAdd()和TryTake().TryAdd()方法尝试给集合加入一项,但假设集合禁止加入项,这个操作可能失败.为了给出相关信息,TryAdd()方法返回一个布尔值,以说明操作是成功还是失败.TryTake()方法也以这样的方式工作,以通过调用者操作是成功还是失败,并在操作成功时返回集合中的项.
C#高级编程五十八天----并行集合的更多相关文章
- C++面向对象高级编程(五)类与类之间的关系
技术在于交流.沟通,转载请注明出处并保持作品的完整性. 本节主要介绍一下类与类之间的关系,也就是面向对象编程先介绍两个术语 Object Oriented Programming OOP面向对象编 ...
- C#高级编程四十八天----列表
C#中的List C#中deList怎么样?List<T>类是ArrayList类的泛型等效类,该类使用大小可按需动态增长的数组实现List<T>泛型接口. 泛型的优点:它为使 ...
- C#高级编程五十七天----位数组
位数组 假设须要处理非常多位,就能够使用BitArray类和BitVector32.BitArray位于命名空间System.Collections中. BitVector32位于命名空间System ...
- C#高级编程五十二天----有序列表
有序列表 假设须要基于对全部集合排序,就能够使用SortedList<TKey,TValue>类.这个类依照键给元素排序.这个集合中的值和键都能够使用随意类型. 以下的样例创建了一个有序列 ...
- C#高级编程五十四天----Lookup类和有序字典
Lookup类 Dictionary<Tkey,TValue>仅仅为每一个键支持一个值.新类Lookup<Tkey,TValue>是.NET3.5中新增的,它类似与Dictio ...
- Unix环境高级编程(五)进程环境
本章主要介绍了Unix进程环境,包含main函数是如何被调用的,命令行参数如何传递,存储方式布局,分配存储空间,环境变量,进程终止方法,全局跳转longjmp和setjmp函数及进程的资源限制. ma ...
- C#编程(五十八)----------并行集合
并行集合 对于并行任务,与其相关紧密的就是对一些共享资源,数据结构的并行访问.经常要做的就是对一些队列进行加锁-解锁,然后执行类似插入,删除等等互斥操作. .NET4提供了一些封装好的支持并行操作数据 ...
- 【读书笔记】.Net并行编程(三)---并行集合
为了让共享的数组,集合能够被多线程更新,我们现在(.net4.0之后)可以使用并发集合来实现这个功能.而System.Collections和System.Collections.Generic命名空 ...
- (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
随机推荐
- hdu(2846)Repository
Problem Description When you go shopping, you can search in repository for avalible merchandises by ...
- h5-登录
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- 在centos上面开机自启动某个程序
Systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置.可以通过 systemctl --version 命令来查看使用的版本 常用命令 # 立即启动一个服务 $ s ...
- Redis学习笔记(一) 初识 Redis
简介 我所在的公司是一个以线下业务为主的公司,软件这一块的东西可以说是手工作坊,技术上的东西全靠大家自己折腾.最近也是觉得自己在社会主义的怀抱里安逸了太久,要提高思想政治觉悟,不能忘了资本主义的黑暗, ...
- Oracle Access和filter的区别
在查看Oracle执行计划的时候经常会遇到Access和filter,脑容量太小,总是分不清两者的区别...稍作整理. Access:表示对应的谓词条件会影响数据的访问路径(是按照索引还是表) Fil ...
- 洛谷P3704 [SDOI2017]数字表格
题目描述 Doris刚刚学习了fibonacci数列.用f[i]f[i] 表示数列的第ii 项,那么 f[0]=0f[0]=0 ,f[1]=1f[1]=1 , f[n]=f[n-1]+f[n-2],n ...
- CSS3渐变知识的介绍
渐变是CSS3当中比较丰富多彩的一个特性,通过渐变我们可以实现许多炫丽的效果,有效的减少图片的使用数量,并且具有很强的适应性和可扩展性. 可分为线性渐变.径向渐变 1 线性渐变 linear-g ...
- 解决JSP页面中文乱码插入到数据库的问题
在JSP页面使用表单注册一个用户名的时候,查看到数据库里面的表中文显示乱码的情况有两种: 1.JSP页面传进来的参数中文就是乱码,则是前台的问题,这个时候写一个过滤器就好了,可以写如下的一个过滤器 p ...
- luogu P5290 [十二省联考2019]春节十二响 优先队列_启发式合并
思维难度不大,在考上上写的启发式合并写错了,只拿了 60 pts,好难过QAQ 没什么太难的,在考场上想出链的部分分之后很容易就能想到正解.没错,就是非常短的启发式合并.注意一下,写的要漂亮一点,否则 ...
- Day73-CMDB(资产管理采集)的三种实现方式
# 采集数据 import subprocess import requests ret = subprocess.getoutput('ipconfig') # print(ret) # 正则处理获 ...