刚才想了半天文章应该起什么名字,最后决定起名为《线程安全使用》,线程安全这个词很难理解,感觉就像托管这词一样,但是托管翻译成英文是managed,我通常把他翻译成被管理,这样就好理解多了,线程安全也是一样,可以理解为可以被多个线程同时使用的集合,而且同时使用的时候是该集合的值是准确的。
MSDN将在System.Collections.Concurrent命名空间下的集合,都称为线程安全的集合。
下面举一个使用线程安全集合的例子,使用的是BlockingCollection,个人觉得这个集合是够用了,其他集合和这个集合基本上大同小异,没什么大区别。但是根据官方解释ConcurrentBag是适用于快速删除和添加,具体为什么他适用,而BlockingCollection不适用,我也没找到原因。
<span >namespace<span > ParallelConsole{
<span >class<span > Program
{
</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">定义集合大小为51个,也可以不定义大小</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">static</span> BlockingC<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>lection<<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">int</span>> blocking = <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">new</span> BlockingC<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>lection<<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">int</span>>(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800080;">51</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;">); </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">static</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">vo<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a></span> Main(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">string</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;">[] args) { blocking </span>= <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">new</span> BlockingC<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>lection<<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">int</span>><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;">(); Cons<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>e.Write<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>ne(</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">当前blocking为:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span> + blocking.IsCompleted + <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"><a href="https://m.jb51.cc/tag/shezhi/" target="_blank" >设置</a>了集合大小count一样是0,blocking.Count:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span> +<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"> blocking.Count()); </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">当前线程标识</span>
<span > Console.Writeline(Thread.CurrentThread.GetHashCode());
</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">for</span> (<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">int</span> i = <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800080;">0</span>; i < <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800080;">3</span>; i++<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;">) { </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #808080;">///</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">/如果<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" >添加</a>到第3个,就<a href="https://m.jb51.cc/tag/shezhi/" target="_blank" >设置</a><a href="https://www.jb51.cc/tag/tianjia/" target="_blank" >添加</a>完成,这时在<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" >添加</a>就会抛异常</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">if (i == 3) </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">{ </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"> blocking.CompleteAdding(); </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">}</span>
<span >
Action
Task task = <span >new<span > Task(action,i);
task.RunSynchronously();
}
Console.Writeline(<span >"<span >设置添加完成前:<span >" +<span > blocking.IsAddingCompleted);
<span >//<span >设置添加完成后
<span > blocking.CompleteAdding();
Console.Writeline(<span >"<span >设置添加完成后:<span >" +<span > blocking.IsAddingCompleted);
<span >#region 同步取 取3个
<span >//<span >for (int i = 0; i < 3; i++)
<span >//<span >{
<span >//<span > Action actionTake = new Action(take);
<span >//<span > actionTake();
<span >//<span >}
<span >#endregion
<span >//<span >并发读取
<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">#region</span> 并发步取 取3个 <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">blocking.IsCompleted 只有当集合被<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" >添加</a>进<a href="https://www.jb51.cc/tag/neirong/" target="_blank" >内容</a>,<a href="https://m.jb51.cc/tag/ranhou/" target="_blank" >然后</a>又都被取光了以后,他才会等于ture,否则都是false </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">当IsCompleted为ture时,就不能再取了否则会抛异常 </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">同时取,结果是 </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">blocking:0 </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">blocking:2 </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">blocking:1</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">if</span> (!blocking.IsCompleted)<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">如果集合没取光</span>
<span > {
Action actionTake2 = <span >new<span > Action(take);
Parallel.Invoke(actionTake2,actionTake2,actionTake2);
}
<span >#endregion<span >
Cons<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>e.Write<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>ne(</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">当前blocking为:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span> + blocking.IsCompleted + <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">,blocking<a href="https://www.jb51.cc/tag/shuliang/" target="_blank" >数量</a>为:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span> +<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"> blocking.Count()); </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">数据被取光了以后, blocking.Count()为0</span>
<span > Console.Read();
}
</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">pub<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>c</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">static</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">vo<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a></span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"> take() { </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;">//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"><a href="https://m.jb51.cc/tag/tongbu/" target="_blank" >同步</a>取,blocking.Count()会真实的表现,而异步取,Count是不准确的,因为我取count的时候,可能集合已经又被取出数据了,测试10次肯定会出现不真实的情况</span> Cons<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>e.Write<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>ne(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">blocking:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span> + blocking.Take() + <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">,blocking<a href="https://www.jb51.cc/tag/shuliang/" target="_blank" >数量</a>为:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;">"</span> +<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"> blocking.Count()); } </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">pub<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>c</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">static</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">vo<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a></span> run(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">object</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"> i) { </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">int</span> currentI = <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;">int</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;">.Parse(i.ToString()); blocking.TryAdd(currentI); }}
}
解释几个方法:
Parallel.Invoke(),并发调用ACtion,可以传多个action,也可以传一个action数据组。
Task(action
task.RunSynchronously(),根据MSDN解释,他是同步运行任务计划用的,同时他和task.Start()一样,也可以启动线程。
BlockingCollection集合
属性一:IsCompleted,他是表示集合是否有数据,只有当集合被添加进内容,然后又都被取光了以后,他才会等于ture,否则都是false。
PS:这个解释如果你要看MSDN一辈子都想不明白,msdn的中文翻译真心坑。
属性一:BlockingCollection.IsAddingCompleted,表示是否添加完成。针对blocking.CompleteAdding()的使用,当调用了该方法IsAddingCompleted就为true。
方法一:BlockingCollection.blocking.CompleteAdding(),设置IsAddingCompleted用的。
方法二:BlockingCollection.Add,添加一个实体
方法三:BlockingCollection.TryAdd,添加一个实体,我这里用的是这个方法,区别是,如果添加重复项,他会引发InvalIDOperationException这个异常。
方法四:BlockingCollection.Take,从集合中取一个值,注意,是真的取出来,取出来后,BlockingCollection.cout会减一。
运行结果如下:
今天先写到这,写文字还真是累,明明没写几个字。。。
总结以上是内存溢出为你收集整理的C#线程安全使用(二)全部内容,希望文章能够帮你解决C#线程安全使用(二)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)