标签:安全 int -- List 中间 Add 线程 new
{ List<int> intlist = new List<int>(); for (int i = 0; i < 10000; i++) { intlist.Add(i); } }//正常for循环完毕是 i=9999
{ List<int> intlist = new List<int>(); List<Task> tasklist = new List<Task>(); int k = 0; for (int i = 0; i < 10000; i++) { Task.Run(() => { lock (obj_Lock) { intlist.Add(i); } }); } Task.WaitAll(tasklist.ToArray()); } //多线程循环完 k肯定是小于10000的
线程安全:一段业务逻辑,单线程执行和多线程执行后的结果如果完全一致,是线程安全的;否则就表示是线程不安全;
1.锁,加索--直接是标准锁-- - 锁的本质,是独占引用;加锁以后;反多线程-- - 不再是多线程执行了 - 可以解决线程安全问题-- - 不推荐大家使用--加锁--影响性能
a) 标准写法:
private readonly static object obj_Lock = new object();
lock (obj_Lock) { intlist.Add(i); }
b) 锁对象--不要去锁String 锁 This
2.直接使用单线程?(分块/分区去执行,每一个区块对应一个线程) 把要操作的整块数据,做一个切分:例如有1000条数据,可以把这一万条数据分区、分块;分三块;每一块开启一个线程去执行;三个线程
每一个线程内部执行的动作是单线程--线程安全等待三个线程执行结束以后,再单线程做一个统一汇总;需要把程序加以设计才能完成;
//分块、分区执行解决线程安全问题 { List<int> intlist1 = new List<int>(); List<int> intlist2 = new List<int>(); List<int> intlist3 = new List<int>(); int length = 10000; int Num1 = 3000; int Num2 = 6000; int Num3 = 10000; List<Task> taskList = new List<Task>(); taskList.Add(Task.Run(() => { for (int i = 0; i < Num1; i++) { intlist1.Add(i); } })); taskList.Add(Task.Run(() => { for (int i = Num1; i < Num2; i++) { intlist2.Add(i); } })); taskList.Add(Task.Run(() => { for (int i = Num2; i < Num3; i++) { intlist3.Add(i); } })); Task.WaitAll(taskList.ToArray()); intlist1.AddRange(intlist2); intlist1.AddRange(intlist3); } }
3.使用线程安全对象 看看数据结构 线程安全对象 List/Arraylist 都不是线程安全的集合--把list Arraylist 换成安全对象;
BlockingCollection<int> blockinglist = new BlockingCollection<int>(); ConcurrentBag<int> conocurrentbag = new ConcurrentBag<int>(); ConcurrentDictionary<string, int> concurrentDictionary = new ConcurrentDictionary<string, int>(); ConcurrentQueue<int> concurrentQueue = new ConcurrentQueue<int>(); ConcurrentStack<int> concurrentStack = new ConcurrentStack<int>(); OrderablePartitioner<int> OrderablePartitioner = new OrderablePartitioner<int>(); Partitioner<int> partitionerArray = new Partitioner();
中间变量
{ for (int i = 0; i< 5; i++) { Debug.WriteLine($"ThreadID={Thread.CurrentThread.ManagedThreadId.ToString("00")}_i={i}"); } } //每次打印的i都为5 在循环内部:如果直接变量i,当线程执行的时候:i会变成5;
Task开启线程的时候,延迟开启--(延迟时间很短的); 开启多线程执行不会阻塞主线程;在循环的时候,不会阻塞主线程,循环很快;当有一个线程在正式的执行业务逻辑的时候;循环已经结束了;i已经变成5了
可以另外定义个变量---变量,在每次循环的时候,赋值;循环多少次,就会有多少个k,每个线程使用的是每一次循环内部的k; 在多线程中,使用这个变量的值 { List<Task> tasks = new List<Task>(); for (int i = 0; i < 5; i++) { int k = 0; tasks.Add(Task.Run(() => { Debug.WriteLine($"ThreadID={Thread.CurrentThread.ManagedThreadId.ToString("00")}_i={i}__ k={ k}"); })); } Task.WaitAll(tasks.ToArray()); }
注意这个变量一定要在循环内部去定义,在外部定义在循环内部赋值是不解决问题的
标签:安全,int,--,List,中间,Add,线程,new 来源: https://www.cnblogs.com/soulice/p/15637366.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。