基元线程同步——基础非阻塞同步(volatilereadvolatilewritevolatileinterlocked)

基元线程同步——基础非阻塞同步(volatilereadvolatilewritevolatileinterlocked)

ID:8812839

大小:106.00 KB

页数:10页

时间:2018-04-08

基元线程同步——基础非阻塞同步(volatilereadvolatilewritevolatileinterlocked)_第1页
基元线程同步——基础非阻塞同步(volatilereadvolatilewritevolatileinterlocked)_第2页
基元线程同步——基础非阻塞同步(volatilereadvolatilewritevolatileinterlocked)_第3页
基元线程同步——基础非阻塞同步(volatilereadvolatilewritevolatileinterlocked)_第4页
基元线程同步——基础非阻塞同步(volatilereadvolatilewritevolatileinterlocked)_第5页
资源描述:

《基元线程同步——基础非阻塞同步(volatilereadvolatilewritevolatileinterlocked)》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库

1、一、基元用户模式和内核模式。基元(Primitive):指代码中可以使用的最简单的构造。有两种基元构造:用户模式(user-mode)和内核模式(kernel-mode)。1,用户模式。它是用CPU指令来协调线程,这种协调是在硬件中发生的,所以速度会快于内核模式。但是也意味着,Windows操作系统永远也检测不到一个线程在一个基元用户模式构造上阻塞了。由于在一个基元用户模式构造上阻塞的线程永远不认为已经阻塞,所以线程池不会创建新的线程来替换这种阻塞的线程。另外,这些CPU指令只是阻塞线程极短的时间。缺点:只有Windows系统的内核才

2、能停止一个线程的执行。用户模式中的线程可能会被系统抢占,但很快就会被再次调度。如果一个线程想获得资源又暂时取不到资源,它会一直在用户模式中运行,这会大大浪费CPU的时间。2,内核模式。内核模式的构造是由Windows操作系统自身提供的。它们要求在应用程序的线程中调用操作系统内核的函数。将线程从用户模式切换成内核模式(或相反)会导致巨大的新能损失,这也是为什么要避免使用内核模式的原因。优点:一个线程使用一个内核模式的构造获取一个其它线程拥有的资源时,Windows会阻塞线程,使它不浪费CPU的时间。然后当资源变得可用时,Windows会

3、恢复线程,允许它访问资源。3,“活锁”和“死锁”对于在一个构造上等待的线程,如果拥有这个构造的线程一直不释放它,前者就可能一直阻塞。“活锁”:如果这是一个用户模式的构造,线程将一直在CPU上运行,我们称之为“活锁”。“死锁”:如果这是一个内核模式的构造,http://fz.qqq23.com线程将一直阻塞,我们称之为“死锁”。“死锁”总是优于“活锁”,因为“活锁”既浪费CPU时间又浪费内存,而“死锁”只浪费内存。4,原子操作对简单数据类型进行原子性的读和写。比如:对于32位的cpu,4字节及以下是原子操作。64位的cpu,8字节及以下

4、是原子操作。如对于32位的cpuclassSomeType{publicclassInt32x=0;}我们对它进行赋值:SomeType.x=0x01234567x变量的值会一次性(原子性)从0x00000000变成0x01234567,这期间另一个线程不可能看到一个中间状态的值。但是如果x是一个Int64的类型。SomeType.x=0x0123456789abcdef另一个线程查询x的值,可能得到一个0x0123456700000000或0x0000000089abcdef。因为读写操作不是原子性的。对于32位的cpu必须分两次写

5、入这个数据。5,用户模式构造这种方式是非阻止的同步,主要原理就是用了上面描述的原子操作特性。因为它不刻意阻塞线程,所以速度非常快。Thread.VolatileRead、Thread.VolatileWrite、System.Threading.Interlocked类提供的方法,以及以及C#的volatile关键字都支持原子性的操作。重中之重:上面提到的方法,并不是真正意义上的不阻塞,而是这个阻塞发生在cpu上,是用指令来协调的,阻塞时间非常短而已。例如:如果有5个线程同时访问到Thread.VolatileRead方法,其中4个线

6、程肯定会被阻塞。5.1 VolatileRead和VolatileWrite这两个方法的解释让人非常迷惑,很不容易理解。从字面意思来看,就是进行易失性读取。对于Jeffrey总结的这条规则:当线程通过共享内存相互通信时,调用VolatileWrite来写入最后一个值,调用VolatileRead来读取第一个值。上面的这条规则是怎么的出来的?难道因为Jeffrey是牛人,我们就不动脑袋盲目接受?适度的探寻是必要的。先来看看Thread.MemoryBarrier这个方法的作用:它强迫按照程序的顺序,之前的加载和存储操作必须在Memory

7、Barrier方法之前完成;http://www.zhaicao8.com之后的加载和存储操作必须在MemoryBarrier方法之后完成。这个方法是一个完整的栅栏(fullfence),关于内存栅栏的概念可以google搜索。VolatileRead和VolatileWrite在内部都调用了这个类。publicstaticintVolatileRead(refintaddress){intnum=address;MemoryBarrier();returnnum;}publicstaticvoidVolatileWrite(refi

8、ntaddress,intvalue){MemoryBarrier();address=value;}所以真正起作用的是Thread.MemoryBarrier方法:该方法可以阻止CPU指令的重新排列(也可阻止编译器的优

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。