C#专题之线程

5.1 资源访问冲突问题


internal class StateObject
{private int state = 5;public void ChangeState(){if (state == 5){state++;Console.WriteLine("state: " + state + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state = 5;}
}
static void Main(string[] args)
{StateObject state = new StateObject();for (int i = 0; i < 100; i++){Thread t = new Thread(state.ChangeState);t.Start();}
}

解决——加锁

internal class StateObject
{private Object _lock = new Object();private int state = 5;public void ChangeState(){lock (_lock){if (state == 5){state++;Console.WriteLine("state: " + state + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state = 5;}}
}

异步委托的方式启动线程


static void Test()
{Console.WriteLine("Test Started");Console.WriteLine("Test Running");Thread.Sleep(3000);Console.WriteLine("Test Completed");
}delegate void TestDelegate();static void Main(string[] args)
{TestDelegate testDelegate = Test;testDelegate.BeginInvoke(null, null);Console.WtiteLine("Main Completed");
}

线程的优先级和线程的状态


线程的优先级

在 Thread 类中,可以设置 Priority​ 属性,以影响线程的基本优先级,Priority​ 属性是 ThreadPriority​ 枚举定义的一个值。定义的级别有:Highest​、AboveNormal​、Normal​、BelowNormal​ 和 Lowest​。

线程的状态

  • 获取线程的状态(Running 还是 Unstarted…),当我们通过调用 Thread 对象的 Start() 方法,可以创建线程,但是调用了 Start()​ 方法之后,新线程不是马上进入 Running 状态,而是处于 Unstarted 状态,只有当操作系统的线程调度器选择了要运行的线程,这个线程的状态才会修改为 Running 状态。我们使用 Thread.Sleep()​ 方法可以让当前线程休眠进入 WaitSleepJoin 状态。
  • 使用 Thread对象的 Abort()​ 方法可以停止线程。调用这个方法,会在要终止的线程中抛出一个 ThreadAbortException​ 类型的异常,我们可以 try catch 这个异常,然后在线程终止前做一些清理的工作。
  • 如果需要等待线程的结束,可以调用 Thread 对象的 Join()​ 方法,表示把 Thread 加入进来,暂停当前线程,并把它设置为 WaitSleepJoin 状态,直到加入的线程完成为止。

线程池


static void Main(string[] args)
{for (int i = 0; i < 10; i++){ThreadPool.QueueUserWorkItem(Download);}Thrad.Sleep(500);
}static void Download(Object state)
{for (int i = 0; i < 3; i++){Console.WriteLine("Downloading...: " + Thread.CurrentThread.ManageThreadId);Thread.Sleep(100);}
}
  • 使用线程池启动的线程默认是后台线程
  • 如果进程的所有前台线程都结束了,所有的后台线程就会停止,不能把入池的线程改为前台线程。
  • 不能给入池的线程设置优先级或名称
  • 入池的线程只能用于时间较短的任务,如果线程要一直运行,就应该使用 Thread​ 类创建一个线程。

死锁问题


internal class StateObject
{private Object _lock1 = new Object();private Object _lock2 = new Object();private int state1 = 5;private int state2 = 5;public void ChangeState(){Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第1把锁");lock (_lock1){lock (_lock2){Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第2把锁");if (state1 == 5){state1++;Console.WriteLine("state: " + state1 + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state1 = 5;if (state2 == 5){state2++;Console.WriteLine("state: " + state2 + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state2 = 5;}}}public void ChangeState(){lock (_lock2){Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第2把锁");lock (_lock1){Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第1把锁");if (state1 == 5){state1++;Console.WriteLine("state: " + state1 + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state1 = 5;if (state2 == 5){state2++;Console.WriteLine("state: " + state2 + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state2 = 5;}}}
}

解决方法——规定相同的拿锁顺序

internal class StateObject
{private Object _lock1 = new Object();private Object _lock2 = new Object();private int state1 = 5;private int state2 = 5;public void ChangeState(){Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第1把锁");lock (_lock1){lock (_lock2){Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第2把锁");if (state1 == 5){state1++;Console.WriteLine("state: " + state1 + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state1 = 5;if (state2 == 5){state2++;Console.WriteLine("state: " + state2 + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state2 = 5;}}}public void ChangeState(){lock (_lock1){Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第1把锁");lock (_lock2){Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第2把锁");if (state1 == 5){state1++;Console.WriteLine("state: " + state1 + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state1 = 5;if (state2 == 5){state2++;Console.WriteLine("state: " + state2 + " 线程ID:" + Thread.CurrentThread.ManageThreadId);}state2 = 5;}}}
}

使用Thread启动线程和传输数据


启动线程

static void Test()
{Console.WriteLine("Test Started");Console.WriteLine("Test Running");Thread.Sleep(1000);Console.WriteLine("Test Completed");
}static void Main(string[] args)
{Thread t = new Thread(Test);t.Start();Console.WriteLine("Main Completed");
}

使用 Lambda 表达式:

static void Main(string[] args)
{Thread t = new Thread(() => Console.WriteLine("Child Thread: " + Thread.CurrentThread.ManageThreadId));t.Start();Console.WriteLine("Main Completed: " + Thread.CurrentThread.ManageThreadId);
}

使用匿名方法:

static void Main(string[] args)
{Thread t = new Thread(delegate () {Console.WriteLine("Child Thread: " + Thread.CurrentThread.ManageThreadId)});t.Start();Console.WriteLine("Main Completed: " + Thread.CurrentThread.ManageThreadId);
}

传递数据

static void Download(Object x)
{string str = o as string;Console.WriteLine(str);
}static void Main(string[] args)
{Thread t = new Thread(Download);t.Start("http://www.xxx.com");
}

Start()​ 方法只能接收无参的方法或只有一个参数的方法

传递多个数据

public struct Data
{public string message;public int age;
}static void Download(Object x)
{Data data = (Data)o;Console.WriteLine(data.message);Console.WriteLine(data.age);
}static void Main(string[] args)
{Data data = new Data();data.message = "";data.age = 12;  Thread t = new Thread(Download);t.Start(data);
}

任务


static void Main(string[] args)
{TaskFactory tf = new TaskFactory();Task t = tf.StartNew(Test);Thread.Sleep(5000);
}static void Test()
{for (int i = 0; i < 10000; i++){Console.WriteLine("A");}
}
static void Main(string[] args)
{Task t = new Task(Test);t.Start();Thread.Sleep(5000);
}static void Test()
{for (int i = 0; i < 10000; i++){Console.WriteLine("A");}
}

连续任务

如果一个任务t1的执行是依赖于另一个任务t2的,那么就需要在这个任务t2执行完毕后才开始执行t1。这个时候我们就可以使用连续任务。

static void FirstDownload()
{Console.WriteLine("Downloading ...");Thread.Sleep(2000);
}static void SecondAlert(Task t)
{Console.WriteLine("下载完成!");
}static void Main(string[] args)
{Task t1 = new Task(FirstDownload);t1.ContinueWith(SecondAlert);t1.Start();Thread.Sleep(5000);
}
static void FirstDownload()
{Console.WriteLine("Downloading ...");Thread.Sleep(2000);
}static void SecondAlert(Task t)
{Console.WriteLine("下载完成!");
}static void Main(string[] args)
{Task t1 = new Task(FirstDownload);Task t2 = t1.ContinueWith(SecondAlert);Task t3 = t2.ContinueWith(SecondAlert);t1.Start();Thread.Sleep(5000);

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

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

相关文章

关于读完《额尔古纳河右岸》后的一些感受

一点废话 我本是一个喜欢读书的人&#xff0c;爱读那些有深意的书籍&#xff0c;而非现在这些《数据结构》、《LINUX 高级编程》、《编译原理》等技术性书籍。读它们时&#xff0c;我的的目的性很强&#xff0c;就是想了解它&#xff0c;思考如何运用到工作中。虽然时常也会因…

Android上编译和使用curl

1 概述 Android系统编译的时候默认是没有带curl工具的&#xff0c;但是在aosp源码中&#xff0c;却是有curl的源码包含。所以只需要编译curl&#xff0c;然后将其push到Android设备中&#xff0c;就可以使用curl命令了。 2 编译curl 这里编译curl是在整机代码环境下进行编译…

24年嘉兴市索贝进出口有限公司--信息安全实施项目

截至24年6月24日&#xff0c;oms生产环境订单数12万5673条。 索贝是一家致力于成为竹木小家具头部企业的公司&#xff0c;截至24年6月24日&#xff0c;在册员工数130人&#xff0c;产值10个亿。 由于信息安全人才和能力的缺失&#xff0c;导致部署在阿里云生产环境的系统处于…

Spring_Bean

概述 bean是一种特殊的Java类 具有私有属性和公共getter和setter方法实现了可序列化接口具有无参构造函数 简单来说&#xff0c;bean就是一个类对象 在Spring中&#xff0c;bean是由Spring的IOC容器进行管理的&#xff0c;IOC容器中存放的就是一个个Bean对象 内容 id&…

Qt添加Dialog对话框

Qt版本&#xff1a;5.12.12 1.添加【模块】 Base class&#xff1a;可以选择QDialog、QWidget、QMainWindow 会自动生成MyDialog.h和MyDialog.cpp文件以及MyDialog.ui文件&#xff0c; 2.添加代码&#xff1a; &#xff08;1&#xff09;TestDialog.h #pragma once#include…

HarmonyOS开发 - 日志打印

在程序开发过程中&#xff0c;日志输出是不可或缺的一部分。能有效的记录和分析日志数据&#xff0c;使开发人员可以更好地了解程序的运行状况、解决问题、优化性能并满足合规性要求等。 当程序出现错误或异常时&#xff0c;日志记录输出可以帮助开发人员快速定位问题发生的位置…

AIGC 在前端流式获取内容SSE

AIGC 在前端流式获取内容SSE 简介具体实现 简介 在 OpenAI 的 API 中&#xff0c;SSE 通常用于实现实时数据传输。例如&#xff0c;在聊天模型&#xff08;如 ChatGPT&#xff09;中&#xff0c;使用 SSE 可以让客户端实时接收到生成的对话内容&#xff0c;而不需要等待整个响…

React官方文档学习记录

官方文档&#xff1a;React 代办&#xff1a;组件通信的方式&#xff1b; 1 标签语法JSX 你必须闭合标签&#xff0c;如 <br />。你的组件也不能返回多个 JSX 标签。你必须将它们包裹到一个共享的父级中&#xff0c;比如 <div>...</div> 或使用空的<>…

CppInsights: 学习C++模版的神器

CppInsights&#xff1a;深入理解C代码的利器 C是一门强大而复杂的编程语言&#xff0c;其复杂性主要体现在语言的多层次抽象和丰富的语法特性上。尽管这些特性使得C能够高效地处理复杂的任务&#xff0c;但也给开发者带来了理解和调试代码的巨大挑战。CppInsights正是在这一背…

【LeetCode】每日一题:排序链表

给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 解题思路 主要是归并排序&#xff0c;即分治思想&#xff0c;两个数组都有序了之后再双指针合并。这个过程当中&#xff0c;链表排序涉及到&#xff1a; 1、如何寻找到中点来二分&#xff1a;快…

php composer 报错

引用文章&#xff1a; Composer设置国内镜像_composer 国内源-CSDN博客 php composer.phar require --prefer-dist yiidoc/yii2-redactor "*" A connection timeout was encountered. If you intend to run Composer without connecting to the internet, run the …

【Docker】rancher 管理平台搭建

目录 1. 所有节点安装docker 2. 所有节点配置/etc/sysconfig/docker 文件修改如下配置 3. 配置证书 4. 镜像仓库导入镜像 5. 创建镜像仓库 5.1 查询上传的 image id 5.2 镜像打标签 5.3 镜像上推 6. server 节点 7. client 节点 8. 在 server 节点启动 9. 查看运行…

SHELL/作业/2024/6/25

终端输入两个数&#xff0c;判断两数是否相等&#xff0c;如果不相等&#xff0c;判断大小关系 #!/bin/basha$1b$2 if [ $a -eq $b ]then echo "ab"elif [ $a -gt $b ]thenecho "a>b"elseecho "a<b"fi2.已知网址www.hqyj.com…

vivado AUTOPIPELINE_MODULE、AUTOPIPELINE_INCLUDE

自动管道模块 AUTOPIPELINE_MODULE属性为所有组建立一个单独的名称空间 在整个子层次结构中定义的名称。它必须设置在包括的层次结构上 GROUP和AUTOPIPELINE_ LIMIT标记的网络。它也必须使用 当在设计中多次实例化具有自动流水线特性的模块时。 参见Vivado Design Suite用户指南…

算法训练营day20--235. 二叉搜索树的最近公共祖先+701.二叉搜索树中的插入操作 +450.删除二叉搜索树中的节点

一、235. 二叉搜索树的最近公共祖先 题目链接&#xff1a;https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/ 文章讲解&#xff1a;https://programmercarl.com/0235.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91…

PointCloudLib-开发环境搭建-C++

简介 PCL(Point Cloud Library)是在吸收了前人点云相关研究基础上建立起来的大型跨平台开源C++编程库,它实现了大量点云相关的通用算法和高效数据结构,涉及到点云获取、滤波、分割、配准、检索、特征提取、识别、追踪、

Linux源码阅读笔记04-实时调度类及SMP和NUMA

Linux进程分类 实时进程普通进程 如果系统中有一个实时进程并且可执行&#xff0c;调度器总是会选择他&#xff0c;除非有另外一个优先级高的实时进程。SCHED_FIFO&#xff1a;没有时间片&#xff0c;被调度器选择之后&#xff0c;可以运行任意长的时间。SCHED_RR&#xff1a;有…

c++: 理解编译器在背后所做的工作-工具篇

理解C模板以及编译器的优化是深入掌握C编程的重要部分。有一些其他工具和技术可以帮助你更好地理解编译器在背后所做的工作&#xff0c;特别是优化方面。以下是一些有用的工具和技术&#xff1a; 1. Compiler Explorer (Godbolt) Compiler Explorer 是一个非常流行的在线工具…

MybatisPlus 的入门与实践:IService接口 实现 CRUD,简化数据库操作

引言 在MybatisPlus框架中&#xff0c;IService接口扮演着重要的角色。作为一个通用的服务接口&#xff0c;IService定义了一系列数据库操作方法&#xff0c;包括查询、插入、更新、删除等。这些方法的定义使得在服务层进行数据库操作变得更为便捷和高效。 IService 概述 My…

Attention系列总结-粘贴自知乎

1. 梦想做个翟老师&#xff1a;阿里&#xff1a;Behavior Sequence Transformer 解读48 赞同 7 评论文章 优点:捕捉用户行为历史序列中的顺序信息。w2v也是捕捉用户序列信息的,本质差异在于啥&#xff1f; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff0…