C#多线程入门概念及技巧

C#多线程入门概念及技巧

  • 一、什么是线程
    • 1.1线程的概念
    • 1.2为什么要多线程
    • 1.3线程池
    • 1.4线程安全
      • 1.4.1同步机制
      • 1.4.2原子操作
    • 1.5线程安全示例
      • 1.5.1示例一
      • 1.5.2示例二
    • 1.6C#一些自带的方法实现并行
      • 1.6.1 Parallel——For、ForEach、Invoke
      • 1.6.1 PLINQ——AsParallel、AsSequential、AsOrdered
    • 1.7Semaphore

一、什么是线程

1.1线程的概念

  1. 线程是操作系统中能够独立运行的最小单位,也是程序中能够并发执行的一段指令序列
  2. 线程是进程的一部分,一个进程可以包括多个线程,这个线程可以共享进程的资源
  3. 进程有入口线程,也可用创建更多的线程

1.2为什么要多线程

  1. 批量重复任务希望同时进行
  2. 多个不同任务希望同时进行,并且互不干扰

1.3线程池

  1. 一组预先创建的线程,可以被重复使用来执行多个任务
  2. 避免频繁地创建和销毁线程,从而减少了现成创建和销毁的开销,提高了系统的性能和效率
  3. 异步编程默认使用线程池

1.4线程安全

多个线程访问共享资源时,对共享资源的访问不会导致数据不一致或不可预期的结果

1.4.1同步机制

  1. 用于协调和控制多个线程之间的执行顺序和互斥访问共享资源
  2. 确保线程按照特定的顺序执行,避免竞态条件和数据不一致的问题

1.4.2原子操作

  1. 在执行过程中不会被中断的操作,不可分割,要么完全执行,要么完全不执行,没有中间状态
  2. 在多线程环境下,原子操作能够保证数据的一致性和可靠性,避免出现竞太条件和数据竞争的问题

1.5线程安全示例

1.5.1示例一

两个线程对一个变量进行操作,每个线程都让count增加10000,代码如下:

namespace ThreadStudy
{class Thread_Lock{const int total = 100_000; public static int count = 0;static void Main(string[] args){Thread thread1 = new Thread(new ThreadStart(ThreadMethod));Thread thread2 = new Thread(new ThreadStart(ThreadMethod));thread1.Start();thread2.Start();thread1.Join();thread2.Join();Console.WriteLine($"Count:{count}");}public static void ThreadMethod(){for (int i = 0; i < total; i++)count++;}}
}

输出结果确不为两万,并且每次都不一样:

在这里插入图片描述
这是因为线程一在访问并修改这个变量值的时候,另一个线程也在访问并修改这个值,这就会导致一个线程修改后的值被另一个线程修改后的值给覆盖,这个时候我们就需要加锁,修改后的代码如下:

    class Thread_Lock{const int total = 100_000; public static int count = 0;public static object lockobjcet = new object();static void Main(string[] args){Thread thread1 = new Thread(new ThreadStart(ThreadMethod));Thread thread2 = new Thread(new ThreadStart(ThreadMethod));thread1.Start();thread2.Start();thread1.Join();thread2.Join();Console.WriteLine($"Count:{count}");}public static void ThreadMethod(){for (int i = 0; i < total; i++){lock (lockobjcet)count++;//这么写也可用 原子操作://count++在底层可能经过了很多步才加一 这个过程中数据可能被其它线程更改//原子操作能一步完成,防止其它线程对变量进行更改//Interlocked.Increment(ref count);}}}

输出结果:
在这里插入图片描述

1.5.2示例二

正常结果是要输出0-19,不加锁的情况下就会输出一些无序数

public static Queue<int> queue = new Queue<int>();public static object lockObject = new object();static void Main(string[] args){Thread producer = new Thread(new ThreadStart(AddNumber));Thread consumer1 = new Thread(new ThreadStart(WriteNumber));Thread consumer2 = new Thread(new ThreadStart(WriteNumber));producer.Start();consumer1.Start();consumer2.Start();producer.Join();consumer1.Interrupt();consumer2.Interrupt();consumer1.Join();consumer2.Join();}public static void AddNumber(){for (int i = 0; i < 20; i++){Thread.Sleep(20);queue.Enqueue(i);}}public static void WriteNumber(){try{while (true){lock(lockObject)if (queue.TryDequeue(out var res)){Console.WriteLine(res);Thread.Sleep(1);}}}catch (Exception){Console.WriteLine("Thread interrupted");}}

输出结果:
在这里插入图片描述

1.6C#一些自带的方法实现并行

1.6.1 Parallel——For、ForEach、Invoke

正常For循环需要4s

class Program{static void Main(string[] args){var sw = Stopwatch.StartNew();for (int i = 0; i < 20; i++){Thread.Sleep(200);Console.WriteLine($"I:{i}");}Console.WriteLine($"Elapsed time: {sw.ElapsedMilliseconds}ms");}}

在这里插入图片描述
使用Parallel进行For循环:
效果提升近10倍,美滋滋

class Program{static void Main(string[] args){var sw = Stopwatch.StartNew();for (int i = 0; i < 20; i++){Thread.Sleep(200);Console.WriteLine($"I:{i}");}Console.WriteLine($"Elapsed time: {sw.ElapsedMilliseconds}ms");}}

在这里插入图片描述

1.6.1 PLINQ——AsParallel、AsSequential、AsOrdered

//ToDo 后续补充

1.7Semaphore

Semaphore可以控制线程开启的多少,比如Parallel.For开启了5个线程,而Semaphore定义只能开启三个,当有三个线程正在做时,那么其它的线程就不能够再做,Semaphore等待后要释放掉,最后面还需要Dispose,之前用Parallel在不控制线程的情况下需要400ms,现在控制线程数量,需要1400ms

        static void Main(string[] args){var sw = Stopwatch.StartNew();//第一个参数 最开始有几个线程可以用 第二个参数 最多可以同时用几个线程var seamphore = new Semaphore(3, 3);Parallel.For(0, 20, i =>{seamphore.WaitOne();Thread.Sleep(200);Console.WriteLine($"I:{i}");seamphore.Release();});seamphore.Dispose();Console.WriteLine($"Elapsed time: {sw.ElapsedMilliseconds}ms");}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI机器学习实战 | 使用 Python 和 scikit-learn 库进行情感分析

专栏集锦&#xff0c;大佬们可以收藏以备不时之需 Spring Cloud实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏&#xff1a;https:/…

Springboot-aop的使用

aop:面向切面编程&#xff0c;可以看作是面向对象的补充 举例 1.依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.1</version><relativePath/>…

流量分析(信息安全铁人三项赛分区赛2-5.18)

题目描述 目录 题目描述 黑客的IP是多少 服务器1.99的web服务器使用的CMS及其版本号(请直接复制) 服务器拿到的webshell的网址(请输入url解码后的网址) 服务器1.99的主机名 网站根目录的绝对路径(注意最后加斜杠) 黑客上传的第一个文件名称是什么 黑客进行内网扫描&am…

立仪科技光谱共焦在半导体领域的应用

半导体技术在近年来以极快的速度发展&#xff0c;对质量和精密度的要求也不断提升。在这样的背景下&#xff0c;用于材料与设备研究的先进检测技术如光谱共焦成像将自然地找到一席之地。下面我们将详细探讨一下光谱共焦在半导体领域中的应用。 光谱共焦技术&#xff0c;通过在细…

微信小程序 解决tab页切换过快 数据出错问题

具体问题&#xff1a;切换tab页切换过快时,上一个列表接口未响应完和当前列表数据冲突 出现数据错误 具体效果如下&#xff1a; 解决方式&#xff1a;原理 通过判断是否存在request 存在中断 并发送新请求 不存在新请求 let shouldAbort false; // 添加一个中断标志 let re…

神领物流 day03-支付微服务 扫码支付业务功能详解

课程安排 支付微服务的需求了解项目中的代码规范阅读渠道管理相关的代码理解分布式锁的应用阅读支付宝扫码支付的代码阅读微信支付扫码支付的代码xxl-job的入门学习读懂同步支付状态的两种方式 1、背景说明 目前支付微服务完成了支付宝和微信的对接&#xff0c;主要实现的功…

冷空气已发货,户外作业者请做好足部保暖

冷空气不间断 多地体验一夜入冬 据中国天气网消息 冷空气正在马不停蹄发货 三分之二国土需羽绒服护体 同时记得做好足部保暖。 在寒风凛冽的冬日中&#xff0c;对于常年在户外工作人员的群体来说&#xff0c;又到了一年里最难熬的时节。他们不畏严寒&#xff0c;在零度以下…

如何在jupyter 上安装Office365-REST-Python-Client

最近工作需要写python代码从sharepoint 上定期load 数据写入到SQL server 中&#xff0c; 首先需要安装 office365 的python库&#xff08;python库名&#xff1a; Office365-REST-Python-Client&#xff09;但是直接安装失败了。 !pip install Office365-REST-Python-Client…

基于引力搜索算法优化概率神经网络PNN的分类预测 - 附代码

基于引力搜索算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于引力搜索算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于引力搜索优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

Python代码运行速度提升技巧!Python远比你想象中的快~

文章目录 前言一、使用内置函数二、字符串连接 VS join()三、创建列表和字典的方式四、使用 f-Strings五、使用Comprehensions六、附录- Python中的内置函数总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项…

leetcode:1576. 替换所有的问号(python3解法)

难度&#xff1a;简单 给你一个仅包含小写英文字母和 ? 字符的字符串 s&#xff0c;请你将所有的 ? 转换为若干小写字母&#xff0c;使最终的字符串不包含任何 连续重复 的字符。 注意&#xff1a;你 不能 修改非 ? 字符。 题目测试用例保证 除 ? 字符 之外&#xff0c;不存…

天机学堂-1、项目搭建,微服务架构设计

1.学习背景 各位同学大家好&#xff0c;经过前面的学习我们已经掌握了《微服务架构》的核心技术栈。相信大家也体会到了微服务架构相对于项目一的单体架构要复杂很多&#xff0c;你的脑袋里也会有很多的问号&#xff1a; 微服务架构该如何拆分&#xff1f; 到了公司中我需要自…