posix多线程有感--POSIX 线程间的内存可视性

pthreads提供了一些有关内存可视性的基本规则。你可以指望所有的标准实现都遵循以下规则:

(1)当线程调用pthread_create时,它所能看到的内存值也是它建立的线程能够看到的。任何在调用pthread_create之后向内存写入的数据,可能不会被建立的线程看到,即使写操作发生在启动新线程之前。

(2)当线程解锁互斥量时看到的内存中的数据,同样也能被后来直接锁住(或通过等待条件变量锁住)相同互斥量的线程看到。同样,在解锁互斥量之后写入的数据不必被其他线程看见,即使写操作发生在其他线程锁互斥量之前。

(3)线程终止(或通过取消操作,或者从启动函数中返回,或者调用pthread_exit)时看到的内存数据,同样能够被连接该线程的其他线程(通过调用pthread_join)看到。当然,终止后写入的数据不会被连接线程看到,即使写操作发生在连接之前。

(4)线程发信号或广播条件变量时看到的内存数据,同样可以被唤醒的其他线程看到。而在发信号或广播之后写入的数据不会被唤醒的线程看到,即使写操作发生在线程被唤醒之前。

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

   其次,任何时刻两个线程需要访问相同的数据时,你就需要应用其中一条内存可视化规则,大多数情况下是指使用互斥量。这不仅是为了保护多个写操作,即使线程只是读数据,它也需要锁住互斥量以确保读到最新的数据值。

  

    当两个线程一个接一个地向同一内存地址写不同的数据时,最终的结果就像是一个线程按照相同的顺序写两次一样。在这两种情况下,都只是一个值保存在内存中。问题在于如何知道哪个写操作最后发生。通过绝对的外部事件测量,可能是处理器A先写入1,几个微秒后处理器B写入2,单这并不意味着最终的结果是“2”。

    为什么?因为微秒从来没有说过有关机器高速缓存和内存总线工作的细节。处理器可能有高速缓存,是用来保存最近从主存中读出数据的拷贝的快速本地内存。在一个“回写”高速缓存系统中,数据最初只是保存在高速缓存中,而在后面的时间写入(刷新)主存。在不保证读写顺序的系统中,高速缓存中的数据块可能在任何处理器认为方便的时候写入主存。如果两个处理器向同一内存地址写不同的数据,则不同的数据将分别保存在两者高速缓存中。最终两个值将写入到主存中,但是是在随机的时刻写入,与写到相应的高速缓存中的顺序无关。

 

 

 

 

posted on 2013-05-03 15:13  胡永光  阅读(110)  评论(0编辑  收藏  举报

导航