http://ifeve.com/mutex-and-memory-visibility/

POSIX内存可见性规则

IEEE 1003.1-2008定义了XBD 4.11内存同步中的内存可见性规则。特别地,POSIX实现保证:

  • pthread_create()同步:任何变量在pthread_create()调用之前修改,对刚由它创建的线程来说是可见的。当变量在pthread_create()之后修改,那么这条规则就不能保证了,即使是在线程开始执行之前修改的。
  • pthread_join()同步:任何变量由某线程在结束之前修改,那回收(join)它的另一线程 在pthread_join()完成后是可见的。
  • mutex操作——pthread_lock(), pthread_timedlock(), pthread_trylock() , pthread_unlock()同步:任何变量由线程对mutex解锁之前修改,对后面成功锁住同一mutex的线程是可见的,请参阅图2。再强调一次,如果锁住另一个mutex,或者根本没有加锁,又或者变量在pthread_unlock之后又被修改的,这一规则不保证。

图2:mutex引入正确的内存可见性

总结

读完本文后,你应该弄明白Cert POS03-C编码规则背后的原因:

POS03-C:请勿使用volatile作为同步原语

只要遵从POSIX的内存可见性规则这条底线,编写出来的代码理所当然是安全的。特别当一个线程写某个值,而另一线程读此值时,即使能保证原子访问,仍需要使用mutex来构造适当的内存同步访问。

Posix 内存可见性:

1 当线程调用pthread_create时,它所能看到的内存值也是它建立的线程能够看到的。任何在调用pthread_create之后向内存写入的数据,可能不会被建立的线程看到,即使写操作发生在启动新线程之前。
2 当线程解锁互斥量时看到的内存中的数据,同样也能被后来直接锁住(或通过等待条件变量锁住)相同互斥量的线程看到。同样,在解锁互斥量之后写入的数据不必被其他线程看见,即使写操作发生在其他线程锁互斥量之前。
3 线程终止(或者通过取消操作,或者从启动函数中返回,或者调用pthread_exit)时看到的内存数据,同样能够被连接该线程的其他线程(通过调用pthread_join)看到。当然,终止后写入的数据不会被连接线程看到,即使写操作发生在连接之前。
4 线程发信号或广播条件变量时看到的内存数据,同样可以被唤醒的其他线程看到。而在发信号或广播之后写入的数据不会被唤醒的线程看到,即使写操作发生在线程被唤醒之前。

在实际应用的使用方法:

首先,确保哪些可能的地方只有一个线程能访问某段数据。线程的寄存器变量不能被其他线程修改。线程分配的堆栈和堆空间是私有的,除非线程将指向该内存的指针传给其他线程。任何放在register或auto变量中的数据可以在随后的某时刻读取,就像在完全同步的程序中一样。在线程间共享的数据越少,需要做的工作越多。

其次,任何时候两个线程需要访问相同数据时,你就需要应用其中一条内存可视化规则,大多数情况下是指使用互斥量,这不仅是为了保护多个写操作,即使线程是读数据,它也需要锁住互斥量以确保读到最新的数据值。
有一些特别的情况下不需要使用互斥量来确保可视性。如果线程设置了一个全局变量,然后创建了一个新线程读取同一个变量,则新线程将看不到旧的变量值(只能看到改过的新的变量值)。但是,若你创建了一个新线程然后再设置变量的值,则新线程可能看不到新的变量值,即使原线程在新线程读取数据之前向变量内写入了新值。

Mutex和内存可见性的更多相关文章

  1. java并发编程(十四)同步问题的内存可见性

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17288243 加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另 ...

  2. 一篇讲Java指令重排和内存可见性的好文

    在这里: http://tech.meituan.com/java-memory-reordering.html 指令重排和内存可见性(缓存不一致)是两个不同的问题. volatile关键字太强,即阻 ...

  3. 一个Java内存可见性问题的分析

    如果熟悉Java并发编程的话,应该知道在多线程共享变量的情况下,存在“内存可见性问题”: 在一个线程中对某个变量进行赋值,然后在另外一个线程中读取该变量的值,读取到的可能仍然是以前的值: 这里并非说的 ...

  4. 1 Java线程的内存可见性

    Java内存的可见性 可见性: 一个线程对共享变量的修改,能够及时被其它线程看到 共享变量: 如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量 Java内存模型(JM ...

  5. JVM并发机制的探讨——内存模型、内存可见性和指令重排序

    并发本来就是个有意思的问题,尤其是现在又流行这么一句话:“高帅富加机器,穷矮搓搞优化”. 从这句话可以看到,无论是高帅富还是穷矮搓都需要深入理解并发编程,高帅富加多了机器,需要协调多台机器或者多个CP ...

  6. 细说Java多线程之内存可见性

    编程这些实践的知识技能,每一次学习使用可能都会有新的认识 一.细说Java多线程之内存可见性(数据挣用)         1.共享变量在线程间的可见性                共享变量:如果一个 ...

  7. 《Java 并发编程实战》读书笔记之二:图文讲述同步的另一个重要功能:内存可见性

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17288243 加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另 ...

  8. God 1.1.1 多线程之内存可见性

    共享变量在线程间的可见性 synchronize实现可见性 volatile实现可见性 指令重排序 as-if-serial语义 volatile使用注意事项 synchronized和volatil ...

  9. 转: 【Java并发编程】之十四:图文讲述同步的另一个重要功能:内存可见性

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17288243 加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另 ...

随机推荐

  1. jquery 获取select框选中的值示例一则

    $('#MODULE_TYPE').change(function(){ var moduleType=$(this).children('option:selected').val();//这就是s ...

  2. php基础28:文件读取

    <?php //1.追加文件内容 // $fp = fopen("test.txt", "a"); // $outString = "this ...

  3. 信息安全系统设计第二次&第四次实验

    实验二 固件设计  实验步骤: 环境配置如同实验一,承接实验一. 1.在虚拟机中编译代码.对于多线程相关的代码,编译时需要加-lpthread 的库. 2.下载调试在超级终端中运行可执行文件 pthr ...

  4. Linux第十一次学习笔记

    异常控制流 异常控制流(ECF)发生在计算机系统的各个层次 在硬件层,硬件检测到的事件会触发控制突然转移到异常处理程序. 在操作系统层,内核通过上下文转换将控制从一个用户进程转移到另一个用户进程. 在 ...

  5. IOS 应用生命周期

    *当第一次运行程序时候:(active)didFinishLaunchingWithOptions(加载完毕)->applicationDidBecomeActive(获取焦点)*当点击home ...

  6. Jsp语法、指令及动作元素

    一.JSP的语法 1.JSP的模板元素:(先写HTML) 就是JSP中的那些HTML标记 作用:页面布局和美化 2.JSP的Java脚本表达式: 作用:输出数据到页面上 语法:<%=表达式%&g ...

  7. Android--自动搜索提示

    一. 效果图 在Google或者百度搜索的时候,在输入关键词都会出现自动搜索的提示内容,类似如下的效果,输入b 则出现包含b的相关词条 二. 布局代码 <?xml version="1 ...

  8. 制衡技术,从Adblock所想到的

    这是一个很特别的东西.可能已经有人发现了它,但是它并非被广泛接受. 对于这个技术的思考来源主要是在安装了Adblock后想到的.这种反作用力的技术,很可能是一片蓝海.而这种技术的产生及推广,对未来社会 ...

  9. .net截取两个字符串中间的内容

    做模拟登录时,需要截取html代码中的名字,返回的字符串内容如下 <span class="welcome">您好<span style="font-s ...

  10. [C#]Attribute特性(3)——AttributeUsage特性和特性标识符

    相关文章   [C#]Attribute特性 [C#]Attribute特性(2)——方法的特性及特性参数 AttributeUsage特性 除了可以定制自己的特性来注释常用的C#类型外,您可以用At ...