C#多线程Task常见问题(二)

news2024/11/15 15:41:48

1 多线程临时变量

2 线程安全和锁lock

3 线程安全策略总结


线程安全和锁lock

线程安全问题:一段程序逻辑在单线程中执行和多线程中执行,结果一致说明线程是安全的;如果结果不同说明线程不安全。

同样先看一个例子:分别用主线程和Task线程池循环10次,并对List数组进行添加,最后打印数组的个数。

            List<int> intList1 = new List<int>();
            //主线程循环10次
            for (int i = 0; i < 10; i++)
            {
                intList1.Add(i);
            }
            Console.WriteLine($"intList1的个数:{intList1.Count.ToString()}");
            //线程池循环10次
            List<int> intList2 = new List<int>();
            List<Task> taskList = new List<Task>();
            for (int i = 0; i < 5; i++)
            {
               
                taskList.Add(Task.Run(() =>
                 {
                     intList2.Add(i);
                 }));
            }
            Task.WaitAll(taskList.ToArray());
            Console.WriteLine($"intList2的个数:{intList2.Count.ToString()}");
            Console.ReadKey();

打印效果:

可以看到主线程运行的List数组个数是10个,多线程是5个。为什么出现这种情况?

 主要原因是:在多线程执行过程中,由于是同时执行多个循环,会存在几个循环同时对一个List数组添加的情况,造成内存资源抢占。

如何解决??????

(1) 通过加锁的方式:普通锁 Object 

该方式的本质是独占引用,即将该块程序变成单线程执行,虽然可以解决多线程问题,但是影响执行性能,不推荐使用。

  private static object obj_lock =new object();//必须是静态类型

=>实例:

        private static object obj_lock = new object();
        static void Main(string[] args)
        {
            
            List<int> intList1 = new List<int>();
            //主线程循环10次
            for (int i = 0; i < 10; i++)
            {
                intList1.Add(i);
            }
            Console.WriteLine($"intList1的个数:{intList1.Count.ToString()}");
            //线程池循环10次
            List<int> intList2 = new List<int>();
            List<Task> taskList = new List<Task>();
            for (int i = 0; i < 10; i++)
            {
               
                taskList.Add(Task.Run(() =>
                 {
                    lock(obj_lock)//上锁
                    {
                      intList2.Add(i);
                    }
                 }));
            }
            Task.WaitAll(taskList.ToArray());
            Console.WriteLine($"intList2的个数:{intList2.Count.ToString()}");
            Console.ReadKey();
        }

打印效果:

 (2) 将多线程任务自定义切分为数个单线程任务,保证了每个单线程内执行数据安全。

假设有10000个任务,可以将这些任务分为若干块,然后调用线程进行处理,最后执行完毕后将结果汇总。 难点:如何合理对任务进行程序切分设计

            int a = 3000;
            int b = 6000;
            int c = 10000;
            List<int> intList1 = new List<int>();
            List<int> intList2 = new List<int>();
            List<int> intList3 = new List<int>();
            var t1 = Task.Run(() =>
            {
                for (int i = 0; i < a; i++)
                {
                    intList1.Add(i);
                }
            });
            var t2= Task.Run(() =>
            {
                for (int i = a; i < b; i++)
                {
                    intList2.Add(i);
                }
            });
            var t3 = Task.Run(() =>
            {
                for (int i = b; i < c; i++)
                {
                    intList3.Add(i);
                }
            });
            Task.WaitAll(new Task[] { t1, t2, t3 });
            intList1.AddRange(intList2);
            intList1.AddRange(intList3);
            Console.WriteLine($"intList1的个数:{intList1.Count.ToString()}");
            Console.ReadKey();

打印效果:

 (3) 使用线程安全对象

 常用的List/ArrayList/Queue等数据结构都不是线程安全数据结构。 将List数组换为BlockingCollection/ConcurrentQueue/ConcurrentDictionary等。需要引入:

using System.Collections.Concurrent;

实例如下:

            //线程池循环10次
            BlockingCollection<int> intList2 = new BlockingCollection<int>(); //采用安全线程数据结构
            List<Task> taskList = new List<Task>();
            for (int i = 0; i < 100; i++)
            {

                taskList.Add(Task.Run(() =>
                {
                   
                        intList2.Add(i);
                   
                }));
            }
            Task.WaitAll(taskList.ToArray());
            Console.WriteLine($"intList2的个数:{intList2.Count.ToString()}");
            Console.ReadKey();

            //打印效果:
            // intList2的个数:100

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/642833.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

唯品会宕机惨案,损失超亿元!故障来时如何迅速应对?

01 事件回顾 对于IT工程师来说&#xff0c;宕机并非新鲜话题&#xff0c;经历过一次服务器宕机&#xff0c;职业生涯才“完整”。但如果事故超过 12 小时&#xff0c;或许会直接造成职业生涯“宕机”。 3月29日发生的突发事件&#xff0c;#唯品会App崩了 冲上热搜&#xff0…

最全整理,完整一套WEB/APP/接口测试测试流程,全面覆盖...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 web测试流程 需求…

Java --- springboot3整合redis

目录​​​​​​​ 一、整合redis 1.1、导入pom依赖 1.2、修改springboot配置文件 1.3、代码测试 二、测试访问redis五大常用数据类型 三、自动配置原理 四、定制化 4.1、解决redis存储序列化乱码问题 4.2、redis客户端使用jedis 一、整合redis 1.1、导入pom依赖 …

【考试】2023年5月软件设计师考试感受

前言❤️ 由于考试地点距离住的地方很远&#xff0c;一个南面一个北面&#xff0c;所以BZ选择了提前一天去到考试地点附近&#xff0c;住在考点附近。吃了晚饭后。到住的地方大概9点多&#xff0c;洗漱完&#xff0c;10点左右开始考前过知识点&#xff0c;复习到凌晨3点左右。…

改进的粒子滤波算法及其应用研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【博客660】prometheus默认5min的lookback机制带来查询的影响

prometheus默认5min的lookback机制带来查询的影响 1、prometheus staleness机制 我发过的&#xff1a;【博客616】prometheus staleness对PromQL查询的影响 官方staleness解析 相关文章&#xff1a;do-prometheus-metrics-have-some-sort-of-freshness-lifetime 相关issue…

全面解析数据治理

摘要 数据治理并不是一种简单的操作行为&#xff0c;而是对数据资产管理行使权力和控制的活动集合&#xff0c;是一种管理和保护数据的方法&#xff0c;是确保准确性、完整性、安全性、可靠性和一致性的关键。 通过数据治理&#xff0c;企业可以更好地掌握现有数据&#xff0…

C语言---认识动态内存管理并实现一个动态通讯录:静态通讯录别来沾边

文章目录 前言&#x1f31f;一、为什么存在动态内存分配&#x1f31f;二、动态内存函数的介绍&#x1f30f;2.1.malloc函数free函数&#x1f30f;2.2.calloc函数free函数&#x1f30f;2.3.realloc函数 &#x1f31f;三、常见的动态内存错误&#x1f30f;3.1.对NULL指针的解引用…

SQL(--修改中--)

目录 一、基本介绍 二、常用函数 集合函数 字符串函数 MYSQL的日期和时间函数 SQL重要的内建日期函数 MYSQL重要的内建日期函数 条件判断函数 三、操作 单表查询 多表查询 使用正则表达式查询 添加&#xff1a; 修改&#xff1a; 删除&#xff1a; 四、…

Linux系统实现虚拟内存教程

Linux系统实现虚拟内存有两种方法&#xff1a;交换分区&#xff08;swap分区&#xff09;和交换文件&#xff0c; 一、交换文件 查看内存&#xff1a;free -m , -m是显示单位为MB&#xff0c;-g单位GB free -g 创建一个文件&#xff1a;touch命令用于修改…

【2023电工杯】A题 电采暖负荷参与电力系统功率调节的技术经济分析 30页论文及python代码

【2023电工杯】A题 电采暖负荷参与电力系统功率调节的技术经济分析 30页论文及python代码 1 题目 A题:电采暖负荷参与电力系统功率调节的技术经济分析 建设以新能源为主体的新型电力系统是应对全球气候变化挑战的重要举措。高比例新能源接入导致电力系统调节能力稀缺&#x…

电厂人员定位管理系统,厂区人员及车辆轨迹可循

随着科技的不断发展&#xff0c;室内定位技术已经逐渐成为电厂管理中不可或缺的一部分。在传统的变电站管理中&#xff0c;由于缺乏有效的定位技术&#xff0c;很难对设备、人员和物资进行精确的管理&#xff0c;导致了效率低下、成本高昂的问题。而现在&#xff0c;通过引入室…

企业必须知道:数字化官网已成为新发展格局

​如今我们生活在一个数据驱动发展的时代&#xff0c;不能顺应时代发展进步的企业就会落后和淘汰。一个新技术时代应运而生&#xff0c;一个数据主导的数字企业时代也必将应声而至。 社交媒体、移动设备、物联网和大数据引发的数字化趋势不仅改变了人们的生活方式而且要求企业…

工厂模式(四)

过气的&#xff0c;终究是过气了 上一章简单介绍了单例模式(三), 如果没有看过,请观看上一章 一. 工厂模式 引用 菜鸟教程里面的单例模式介绍: https://www.runoob.com/design-pattern/factory-pattern.html 工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常…

输电线路可视化监拍装置硬件解决方案

老旧输电线路可视化监控装置 随着我国人口的增长&#xff0c;电力设施的规模也变得越发庞大&#xff0c;人工运检的负担也越来越沉重&#xff0c;而且巡检的时效性也是痛点&#xff0c;于是电网提出智慧可视化管理通道运检的方案&#xff0c;线路在线监测装置成为其基础&#x…

前端开发环境部署问题(高级程序员必备)

很多开发者到了一家新公司&#xff0c;公司发了一台新电脑&#xff0c;对环境安装比较困惑。今天带大家还原&#xff0c;拿到公司电脑&#xff0c;如何安装你需要的各种环境。 一、node安装 官网下载地址&#xff1a; http://nodejs.cn/download/ 根据自己需要下载对应的版…

电脑多久重装一次系统比较好

在长时间使用电脑后&#xff0c;一些用户可能会考虑重装系统来提升性能和稳定性。然而&#xff0c;电脑重装系统的频率是一个有争议的问题。本文将探讨电脑重装系统的最佳频率&#xff0c;以帮助您做出明智的决策。 工具/原料&#xff1a; 系统版本&#xff1a;win7旗舰版 品…

如何使用Leangoo领歌敏捷工具管理Sprint Backlog

什么是Sprint Backlog&#xff1f; Sprint Backlog是Scrum的主要工件之一。在Scrum中&#xff0c;团队按照迭代的方式工作&#xff0c;每个迭代称为一个Sprint。在Sprint开始之前&#xff0c;PO会准备好产品Backlog&#xff0c;准备好的产品Backlog应该是经过梳理、估算和优先…

编译原理期末速成-自上而下分析、消除文法的左递归问题

文章目录 自上而下分析面临的问题文法左递归问题回溯问题 构造不带回溯的自上而下分析算法消除文法的左递归 自上而下分析 自上而下就是从文法的开始符号出发&#xff0c;向下推导&#xff0c;推出句子。 面临的问题 文法左递归问题 左递归在语法分析过程中可能会导致无限循环…

测试员,自己都不上心,就不要抱怨别人对你冷眼旁观

昨日表哥恳请帮他的学生投递一下开发岗的简历&#xff0c;举手之劳&#xff0c;这忙必须得帮。但当发来学生的简历后&#xff0c;我吐槽了“这简历平平无奇&#xff0c;没有任何亮点&#xff0c;如何令人另眼相看&#xff1f;”表哥说&#xff0c;学生经历不多&#xff0c;总不…