无关线程:线程之间没有任何联系,独立运行,互不干扰

相关线程:线程之间有联系,两个线程之间资源共享

临界线程:多个线程共享资源

临界区:访问临界资源代码

同步:两个线程协同工作才能完成同一项任务

相关线程实例:

public static char buffer;public static string str;static void Main(string[] args){// 开写线程Thread th = new Thread(write);th.Start();// 开度线程Thread re = new Thread(delegate() {for (int i = 0; i < str.Length; i++){char ch = buffer;Console.Write(ch); // 醒木非根,半风走一,谈疏君莫,是一说人人人人人人人人人人人人人Thread.Sleep(50);}});re.Start();Console.ReadLine();}/// <summary>/// 写入/// </summary>public static void write(){str = "醒木本非同根生,半生风雨走一程,谈笑疏狂君莫问,却是一位说书人";for (int i = 0; i < str.Length; i++){buffer = str[i];Thread.Sleep(30);}}

打印结果:

醒木非根,半风走一,谈疏君莫,是一说人人人人人人人人人人人人人


造成这种情况的原因是:读写线程时间不相同。


Interlocked(互锁):

使用线程锁Interlocked来解决这个问题

Interlocked的一些属性

Interlocked.Increment(ref value) 数值加一(原子性操作)

Interlocked.Decrement(ref value) 数值减一(原子性操作)

Interlocked.Exchange(ref value1, value2) 交换:把值2赋给值1;返回新值

Interlocked.CompareExchange(ref value1, value2, value3) 实现比较和交换两种功能:值1和值3比较,如果相同,把值2给值1,不相同则不作任何操作;返回原值(多用于判断条件)

Interlocked.Read读取计数器的值

Interlocked.Add使计数器增加指定的值

使用Interlocked改造完成之后的代码:

// 开写线程Thread th = new Thread(write);th.Start();// 开度线程Thread re = new Thread(delegate() {for (int i = 0; i < str.Length; i++){while (Interlocked.Read(ref num) == 0){Thread.Sleep(10);}char ch = buffer;Console.Write(ch);  //Thread.Sleep(50);// 使值减少1Interlocked.Decrement(ref num);}});re.Start();Console.ReadLine();}/// <summary>/// 写入/// </summary>public static void write(){str = "醒木本非同根生,半生风雨走一程,谈笑疏狂君莫问,却是一位说书人";for (int i = 0; i < str.Length; i++){while (Interlocked.Read(ref num) == 1){Thread.Sleep(10);}buffer = str[i];//Thread.Sleep(30);// 使值增加1Interlocked.Increment(ref num);}}

Monitor(管程):

配合try-catch-finally(需要退出exit)或者Lock使用

锁定的对象应该声明为private static object obj = new object();尽量别用公共变量和字符串、this、值类型。


属性和方法:

Enter(Object) 在指定对象上获取排他锁。
Exit(Object) 释放指定对象上的排他锁。
IsEntered 确定当前线程是否保留指定对象锁。
Pulse 通知等待队列中的线程锁定对象状态的更改。
PulseAll 通知所有的等待线程对象状态的更改。
TryEnter(Object) 试图获取指定对象的排他锁。
TryEnter(Object, Boolean) 尝试获取指定对象上的排他锁,并自动设置一个值,指示是否得到了该锁。
Wait(Object) 释放对象上的锁并阻止当前线程,直到它重新获取该锁。

public static char buffer;public static string str;/// <summary>/// 此变量为InterLocked使用/// </summary>public static long num;/// <summary>/// 此变量为Monitor 使用/// </summary>public static object obj = new object();static void Main(string[] args){// 开写线程Thread th = new Thread(write);th.Start();// 开度线程Thread re = new Thread(delegate() {try{for (int i = 0; i < str.Length; i++){/*while (Interlocked.Read(ref num) == 0){Thread.Sleep(10);}//*/// 程序进入临界区,上锁Monitor.Enter(obj);char ch = buffer;Console.Write(ch);  // 通知等待队列中的线程锁定对象状态的更改Monitor.Pulse(obj);// 释放对象上的锁并阻止当前线程,直到它重新获取该锁Monitor.Wait(obj);/*//Thread.Sleep(50);// 使值减少1Interlocked.Decrement(ref num);//*/}}catch (Exception){throw;}finally{Monitor.Exit(obj);}});re.Start();Console.ReadLine();}/// <summary>/// 写入/// </summary>public static void write(){try{str = "醒木本非同根生,半生风雨走一程,谈笑疏狂君莫问,却是一位说书人";for (int i = 0; i < str.Length; i++){/*while (Interlocked.Read(ref num) == 1){Thread.Sleep(10);}//*/// 程序进入临界区,上锁Monitor.Enter(obj);buffer = str[i];// 通知等待队列中的线程锁定对象状态的更改Monitor.Pulse(obj);// 释放对象上的锁并阻止当前线程,直到它重新获取该锁Monitor.Wait(obj);/*//Thread.Sleep(30);// 使值增加1Interlocked.Increment(ref num);//*/}}catch (Exception){throw;}finally {Monitor.Exit(obj);}}

Lock:上锁

Monitor和Lock的区别

1.Lock是Monitor的语法糖。
2.Lock只能针对引用类型加锁。
3.Monitor能够对值类型进行加锁,实质上是Monitor.Enter(object)时对值类型装箱。
4.Monitor还有其他的一些功能。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1FF05HWw-1658305676246)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b7444c97a2c0455693d468fbdc8c09b8~tplv-k3u1fbpfcp-zoom-1.image “1559178866415958.png”)]

使用lock代替try之后:程序变得简洁了一些:仅限于Monitor

static void Main(string[] args){// 开写线程Thread th = new Thread(write);th.Start();// 开度线程Thread re = new Thread(delegate() {for (int i = 0; i < str.Length; i++){lock (obj){/*while (Interlocked.Read(ref num) == 0){Thread.Sleep(10);}//*/char ch = buffer;Console.Write(ch);// 通知等待队列中的线程锁定对象状态的更改Monitor.Pulse(obj);// 释放对象上的锁并阻止当前线程,直到它重新获取该锁Monitor.Wait(obj);/*//Thread.Sleep(50);// 使值减少1Interlocked.Decrement(ref num);//*/} }});re.Start();Console.ReadLine();}/// <summary>/// 写入/// </summary>public static void write(){str = "醒木本非同根生,半生风雨走一程,谈笑疏狂君莫问,却是一位说书人";for (int i = 0; i < str.Length; i++){lock(obj){/*while (Interlocked.Read(ref num) == 1){Thread.Sleep(10);}//*/buffer = str[i];// 通知等待队列中的线程锁定对象状态的更改Monitor.Pulse(obj);// 释放对象上的锁并阻止当前线程,直到它重新获取该锁Monitor.Wait(obj);/*//Thread.Sleep(30);// 使值增加1Interlocked.Increment(ref num);//*/}}}

以上方法对资源消耗比较大,合理使用

有好的建议,请在下方输入你的评论。

欢迎访问个人博客
https://guanchao.site

欢迎访问小程序:

C#(四十二)之线程同步、互锁相关推荐

  1. Java 多线程和并发编程:(二)线程同步 Lock 锁

    线程同步 Lock 锁 1.Lock 锁 2.步骤 3.Lock 与 synchronized 的区别 1.Lock 锁 Lock 锁:对需要上锁的地方上锁 JDK1.5 后新增的功能 与 Synch ...

  2. 【Microsoft Azure 的1024种玩法】四十二. 通过Windows Admin Center快速创建Azure Virtual Machines

    [简介] Windows Admin Center是微软开发的一套可以部署在本地基于浏览器的GUI的工具集平台,其平台可用于管理Windows相关服务器和PC机器,我们可以利用Windows Admi ...

  3. 【Visual C++】游戏开发笔记四十二 浅墨DirectX教程之十 游戏输入控制利器:DirectInput专场...

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/zhmxy555/article/details/8547531 作者:毛星云(浅墨) ...

  4. 【Visual C++】游戏开发笔记四十二 浅墨DirectX教程之十 游戏输入控制利器:DirectInput专场

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8547531 作者:毛星云(浅墨 ...

  5. 【正点原子STM32连载】第四十二章 FLASH模拟EEPROM实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  6. maya批量命名插件_教你玩转MAYA的四十二精华造诣(第一期)

    最近在整理文档时发现我收藏了一篇关于MAYA应用技巧的文章,突然有兴趣看了看,结果发现老版本MAYA中的某些内容很多已经无法应用于新版本.我又上网查了一下,结果发现网上好多帖子和我收藏的这篇内容基本一 ...

  7. OpenCV学习笔记(四十一)——再看基础数据结构core OpenCV学习笔记(四十二)——Mat数据操作之普通青年、文艺青年、暴力青年 OpenCV学习笔记(四十三)——存取像素值操作汇总co

    OpenCV学习笔记(四十一)--再看基础数据结构core 记得我在OpenCV学习笔记(四)--新版本的数据结构core里面讲过新版本的数据结构了,可是我再看这部分的时候,我发现我当时实在是看得太马 ...

  8. 四十二、深入Java中的文件读取操作

    @Author:Runsen @Date:2020/6/8 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件.导致翘课严重,专业排名 ...

  9. JavaScript学习(四十二)—利用工厂模式创建对象以及工厂模式创建对象的不足

    JavaScript学习(四十二)-利用工厂模式创建对象以及工厂模式创建对象的不足 一.利用工厂模式创建对象 工厂模式是JavaScript中的一种设计模式,它的作用是批量创建具有同种属性的对象. 格 ...

  10. 【Visual C++】游戏开发笔记四十二 浅墨DirectX教程之十 游戏输入控制利器 DirectInput专场

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

最新文章

  1. Java课程主观题作业_JAVA课程作业01
  2. Ehcache学习笔记(一)基础入门
  3. 使用Bootstrap制作导航栏
  4. 洛谷 P2181 对角线
  5. oracle decode(nvl(estimate_qty,0),0,1,estimate_qty) 函數
  6. 445.两数相加II(力扣leetcode) 博主可答疑该问题
  7. 程序员代码面试指南 IT名企算法与数据结构题目最优解
  8. 魔兽世界WOW服务器端的模拟器【2010】
  9. 导出指定layer或指定区域layout的GDS
  10. 个人理财管理系统代码
  11. 获取Android设备唯一标识(唯一序列号)
  12. J2SE:总结—基础很重要哈!
  13. RealView MDK的指定位置
  14. mysql主从配置duxi_MySQL 8.0主从(Master-Slave)配置
  15. Oracle-12:伪列rowid和rownum
  16. Django Linux环境安装
  17. 如何撰写计算机SCI论文的引言部分 - 易智编译EaseEditing
  18. 智慧社区的介绍,为什么要做智慧社区
  19. 被小米的智能识物感动到哭
  20. Apollo path_bounds_decider解析

热门文章

  1. 计算机 无法 访问共享网络打印机,打印机不能共享怎么办|无法连接共享打印机的解决方案...
  2. MIMO技术(一)分集与复用
  3. uni-app:搜索关键词并高亮显示,可重复显示
  4. springboot获取客户端IP及IP归属地
  5. Bugku misc 旋转跳跃wp
  6. TPS、RPS和QPS是什么
  7. html弹性布局什么意思,弹性布局display:flex是什么意思
  8. 松翰单片机之汇编编程
  9. cmd如何返回上一级目录,如何进入其他文件目录
  10. win快速打开计算机,这十个“Windows+”使用技巧,打开你的电脑技巧新世界