最近工作闲暇之际,翻阅了以前保存的电子书《C#多线程编程手册》,发现此书同步技术这块写的甚好,于是参考此书并结合实例,对同步技术做一下总结和分析,也算是读书笔记与心得体会吧,并与大家分享。

书中提到的同步技术有很多种,归纳起来常用的方式有以下几种:

1、利用属性标签方式进行方法同步和上下文同步:MethodImplAttribute 类 和 SynchronizationAttribute 类
2、同步代码区:Monitor 类、Lock 关键字、ReaderWriterLock 类。
3、手控同步:AutoResetEvent 类、ManualResetEvent 类、Mutex 类、Interlocked 类

后面的文章我们会依次对以上类或关键字进行介绍,首先我们先来说说Thread类中的Join方法,书中对它的介绍比较简略,但是我觉得它也算是线程间同步方式的一种了,对它的用法也来总结和归纳一下。

MSDN对 Join 方法解释说:在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止或经过了指定时间为止。

哈哈,MSDN的解释永远都是那么的绕嘴,我们还是通过一个简单的控制台程序作为例子来说明一下吧:

首先我们建立一个计算类Calculate,里面包含一个加法线程 ThreadAdd 和一个加法方法,在Add()方法中并让执行运算的线程休眠5秒,代码如下:

//计算类
public class Calculate{public Thread threadAdd; public Calculate() { threadAdd = new Thread(new ThreadStart(Add)); } //加法运算 public void Add() { Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("进入加法计算");             Thread.Sleep(5000); Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("加法运算结果: x={0} y={1} x+y={2}", 1, 2, 1 + 2); } }

然后我们在Main方法中进行调用:

class Program{static void Main(string[] args) { Calculate calculate = new Calculate(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("主线程输出:准备进行加法运算:"); calculate.threadAdd.Start(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("主线程输出:运算完毕"); Console.ReadKey(); } }

运算结果如图:

到这里,我们会发现执行Main() 方法的主线程,并没有等待 执行加法的工作线程,而是直接输出了“运算完毕”,这时候我们的Join() 方法就该上场了,我们对Main() 函数进行修改一下:

 static void Main(string[] args){Calculate calculate = new Calculate(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("主线程输出:准备进行加法运算:"); calculate.threadAdd.Start(); //增加Join  calculate.threadAdd.Join(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("主线程输出:运算完毕"); Console.ReadKey(); }

运行结果如下图:

这样的结果是我们想要的正常输出顺序。运行的时候我们发现,当主线程执行到 calculate.threadAdd.Join(); 的时候,并没有继续执行,一直等到 加法线程 运算完毕之后主线程才继续运行,这不就是和MSDN中解释的一样吗?主线程现在就属于调用线程,当主线程调用了calculate.threadAdd.Join()的时候,就发生了阻塞,直到加法线程运行完毕之后,才继续运行。

现在我们在来看看Join的另外两个重载方法:Join(Int32) 和 Join(TimeSpan),这两个方法其实是一样的,输入参数说白了就是设置阻塞的等待时间,返回值是bool类型,如果线程已终止,则为 true,否则返回 false 。不明白没关系,我们继续来看例子:

我们修改一计算类,再增加一个 减法方法Sub() 和一个执行减法的线程ThreadSub,代码如下:

//计算类public class Calculate{public Thread threadAdd; public Thread threadSub; public Calculate() { threadAdd = new Thread(new ThreadStart(Add)); threadSub = new Thread(new ThreadStart(Sub)); } //加法运算 public void Add() { Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("进入加法计算"); Thread.Sleep(5000); Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("加法运算结果: x={0} y={1} x+y={2}", 1, 2, 1 + 2); } //新增减法运算 public void Sub() { //主要是这里 bool b = threadAdd.Join(1000); Console.ForegroundColor = ConsoleColor.Red; if (b) { Console.WriteLine("加法运算已经完成,进入减法法计算"); } else { Console.WriteLine("加法运算超时,先进入减法法计算"); } Thread.Sleep(2000); Console.WriteLine("进入减法运算"); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("减法运算结果: x={0} y={1} x-y={2}", 10, 2, 10 - 2); } }

Main() 方法修改为:

class Program{static void Main(string[] args) { Calculate calculate = new Calculate(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("主线程输出:准备进行加法和减法两种运算:"); calculate.threadAdd.Start(); calculate.threadSub.Start(); calculate.threadAdd.Join(); calculate.threadSub.Join(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("主线程输出:所有运算完毕"); Console.ReadKey(); } }

运行结果如下:

结果是正确的,我们来分析一下整个的运算过程:

首先,主线程遇到 calculate.threadAdd.Join();  和 calculate.threadSub.Join(); 肯定会发生阻塞,等待这两个线程完成后,才会继续执行,这个不容质疑。然后我们看加法线程和减法线程,这两个线程几乎同时执行,谁先执行,我们是不可预期的。比如先执行加法线程,当执行到Thread.Sleep(5000),的时候,加法线程休眠5s,减法线程由于调用了 threadAdd.Join(1000); 所以减法线程会阻塞1s ,1s 之后由于加法线程还没有执行完成,所以 返回值为 false,减法线程继续执行,减法线程执行完毕后,又过了一会,加法线程才继续执行。这样就会得出我们上面的运行结果。

Thread.Join() 方法的用法这么多了,下一篇 来总结和说明一下  MethodImplAttribute 类 和 SynchronizationAttribute 类。

本 文源 码 下 载

作者:Rising Sun
出处:http://www.cnblogs.com/lxblog/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

转载于:https://www.cnblogs.com/newword/p/8038979.html

【总结】C# 线程同步技术(一)之 Join 方法相关推荐

  1. .Net线程同步技术解读

    C#开发者(面试者)都会遇到lock(Monitor),Mutex,Semaphore,SemaphoreSlim这四个与锁相关的C#类型,本文期望以最简洁明了的方式阐述四种对象的区别. 什么是线程安 ...

  2. 线程同步,通信与虚方法

    线程同步,通信与虚方法 目录 线程同步,通信与虚方法 进程同步,通信 事件event 旗语semaphore 信箱mailbox 虚方法 实例理解 将子类句柄赋值成父类句柄 将父类句柄赋值成子类句柄 ...

  3. JAVA中线程同步的几种实现方法

    JAVA中线程同步的几种实现方法 一.synchronized同步的方法: 1.synchronized同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁, ...

  4. 转:C# 线程同步技术 Monitor 和Lock

    原文地址:http://www.cnblogs.com/lxblog/archive/2013/03/07/2947182.html 今天我们总结一下 C#线程同步 中的 Monitor 类 和 Lo ...

  5. VC++中线程同步技术分析3

    管理事件内核对象 在前面讲述线程通信时曾使用过事件内核对象来进行线程间的通信,除此之外,事件内核对象也可以通过通知操作的方式来保持线程的同步.对于前面那段使用临界区保持线程同步的代码可用事件对象的线程 ...

  6. Visual C++线程同步技术

    线程同步的方式有: 临界区 管理事件内核对象 信号量内核对象 互斥内核对象 分别介绍如下: 使线程同步 在程序中使用多线程时,一般很少有多个线程能在其生命期内进行完全独立的操作.更多的情况是一些线程进 ...

  7. VC线程同步技术剖析

    在程序中使用多线程时,一般很少有多个线程能在其生命期内进行完全独立的操作,更多的情况是一些线程进行某些处理操作,而其他的线程必须对其处理结果进行了解.正常情况下对这种处理结果的了解应当在其处理任务完成 ...

  8. 线程同步的几种实现方法

    一.引言 前几天面试,被大师虐残了,好多基础知识必须得重新拿起来啊.闲话不多说,进入正题. 二.为什么要线程同步 因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会 ...

  9. iOS开发线程同步技术-锁

    概览 1,什么是锁(临界区)? 2,常用的锁有哪些? 3,相关链接 什么是锁(临界区) 临界区:指的是一块对公共资源进行访问的代码,并非一种机制或是算法. 常用的锁有哪些? 互斥锁:是一种用于多线程编 ...

最新文章

  1. 字符串转数字 sql_SQL注入·sqli-labs·基于错误的字符串/数字型注入(第1~2关)
  2. 如何将程序添加到系统服务实现开机自启动
  3. linux tar包 追加
  4. CentOS屏幕录制
  5. python示例库,常用的Python库和示例代码(快速上手)
  6. 限制nginx仅能域名访问,不可用ip访问
  7. 5分钟 0元搭建个人独立博客网站(一)
  8. 数据库-MySQL-搭建服务器
  9. Python批量替换掉某些值为新的值
  10. Golang的time包的应用
  11. 使用axis2解析wsdl反向生成webservice客户端
  12. 职工工作量c语言调试分析,c语言职工工作量统计
  13. 看朋友日志发现的一个ios下block相关的内存管理问题,非常奇怪,请大家帮忙一起来回答!...
  14. C++调用其他语言(C#、java、python)
  15. Android简易天气App
  16. 爬虫练习-爬取小猪短租网北京地区短租房信息
  17. 如何从福彩官网抓取 双色球历史数据
  18. mysql创建表s c sc_MySqL | 小白创建表
  19. PyCharm谷歌翻译插件Translation提示:更新 TKK 失败,请检查网络连接
  20. 电力 Web SCADA 工控组态编辑器

热门文章

  1. 谷歌、DeepMind提出高效Transformer评估基准
  2. linux ruby作用域,细说Ruby细化
  3. pandas时间处理操作
  4. 源码安装mysql 5.1_Linux环境下源码编译安装MySQL5.1
  5. vue传递数组对象_详解vue组件三大核心概念
  6. 在线翻译英文html文件,copy html是什么意思
  7. 豆瓣 为什么不用php,豆瓣网友是不是都疯了?
  8. java+跑多线程_java项目怎么多线程跑单元测试,ide是intellij?
  9. cocos2d-x学习资源汇总(持续更新。。。)
  10. Navicat premium查看数据库表中文注释的两种方式