|
发表于 2010-3-8 05:54:10
|
显示全部楼层
回复【98楼】Gorgon Meducer 傻孩子
-----------------------------------------------------------------------
支持。
回复【99楼】fightman
-----------------------------------------------------------------------
----- 代码0 -----
Initially: p = & x, x = 1, y = 0
Thread 1 | Thread 2
y = 2 | i = *p
memoryBarrier |
p = & y |
Can result in: i = 0
做了很多的解释,最终证明了:一个满了的杯子,是装不进水的。
对于不了解CPU结构的人来说,可以用任何“高级语言”问题来推导出硬件有什么什么问题。
帮你回忆一下整个过程:
在 79楼 :
你依据一个链接 http://www.cs.umd.edu/~pugh/java/memoryModel/AlphaReordering.html 中的代码0
得出结论,“Compaq Alpha SMP机器可能会即使有显式的memoryBarrier下,还是会有内存和cache的同步问题”。
但是,这个结论是错误的。
为了验证我的思想,我专门找到了 Kourosh Gharachorloo (他以离开Compaq,到google工作了),并向他请教了关于代码0的核心问题。
Kourosh Gharachorloo 解释说,这个例子说明了在以 Alpha 21264 构建的 SMP 中由于 “读的乱序” 引起了多线程脏数据,
并给出了解决的方法,就是用MB来保证 Thread 2 中“读”的顺序。
于是,我在 88楼,92楼,95楼 详细的描述和解释了你所谓的问题是如何发生了,如何解决。
我得出的结论是,弱序SMP只需通过MB来保证(读写)代码顺序,就会保证cache和主内存的同步。
到这里为止,我以上的回复,都是在阐述这个问题。
然而,你始终没有正视这个问题,而是和线程的“数据同步”混为一谈。
你的所有回复,89,91,93 都提到了 lock。
从程序的角度来说,lock的目的是为了同步线程的共用数据,
从cpu的角度来说,lock在弱序SMP中它起不到MB(保证代码顺序)的作用。
所以我还要重复这句话:“我逐句分析你的话, 让你明白你思维的错误。”
目的是希望你能倒空你的杯,才能接到新的水。
1)-----------------------------------------------------
MB是什么,wiki上有解释
http://en.wikipedia.org/wiki/Memory_barrier,wiki的解释可以做名词时指一个内存藩篱,或内存边界,
也可以做动词就是指一组代码去完成对原始基础物件或锁无关的数据结构在多处理器系统和跟硬件相关的一些设备的同步。
-----------------------------------------------------
我直接从 wiki 上拷贝过来了:
Memory barrier, also known as membar or memory fence or fence instruction,
is a type of barrier and a class of instruction which causes a central processing unit (CPU)
or compiler to enforce an ordering constraint on memory operations
issued before and after the barrier instruction.
CPUs employ performance optimizations that can result in out-of-order execution.
The reordering of memory operations (loads and stores) normally goes unnoticed
within a single thread of execution, but causes unpredictable behaviour in concurrent programs
and device drivers unless carefully controlled. The exact nature of an ordering constraint
is hardware dependent, and defined by the architecture's memory ordering model.
Some architectures provide multiple barriers for enforcing different ordering constraints.
Memory barriers are typically used when implementing low-level machine code that operates
on memory shared by multiple devices. Such code includes synchronization primitives and lock-free
data structures on multiprocessor systems, and device drivers that communicate with computer hardware.
wiki上的解释和你的不一样啊,如果不是你断章取义,那就是你英文水平有待提高。
简单翻译如下:
MB 是一种 instruction,它的目的是使 CPU 或者 compiler 操作内存时依据“MB之前和之后“的“顺序制约”,
最终防止乱序(CPUs采用乱序来实现效能优化)造成在并行运算中可能带来不可预测的行为(脏数据)或者设备驱动失控。
因此在SMP中操作“同步数据”和“无锁数据”的低级代码中,或者计算机设备驱动中,都包含MB。
所以:
- MB 是一种 instruction (instruction, 就是计算机的元语言)
- MB 提供了 操作内存时依据“MB之前和之后“的“顺序制约”
- lock 和 MB 是没有必然联系的,不要一听到 MB 就说 lock。
2)-----------------------------------------------------
请参看上文给的第一个链接的文章. java的每一个sychronized {}块肯定被JVM整出一个mb出来.
只是我们不知道边界在哪个地方。看似我们可以简单的把块结束的}
之处看做mb的显式切分点,但是诡异的地方是上文给的第一个链接的文章的这些大牛们作者都
说JAVA synchronized块没有显式(Explicit)的MB.
不信大家从头读到尾,从尾读到首.除了敬畏地重温下各位大牛的名号外,真的找不到.
细心的同学可能解读到显式(Explicit)这个关键:这个synchronized块还是有个MB的边界,只是不是Explicit 的.
边界在哪,请各位往下看。
--------------------------------------------------------
本来java里就没有显式(Explicit)的MB,如果有了,就不会出现 "Double-Checked Locking is Broken"。
Double-Checked Locking is widely cited and used as an efficient method for implementing
lazy initialization in a multithreaded environment.
Unfortunately, it will not work reliably in a platform independent way when implemented in Java,
without additional synchronization. When implemented in other languages, such as C++, it depends
on the memory model of the processor, the reorderings performed by the compiler and the interaction
between the compiler and the synchronization library. Since none of these are specified in a
language such as C++, little can be said about the situations in which it will work.
Explicit memory barriers can be used to make it work in C++, but these barriers are not available in Java.
显然你认为,没有 Explicit 的 MB 就一定是 Implicit,这是错的。
Java 中没有 Explicit 的 MB 是指,jave 不能像 c++ 一样直接调用 asm ("memoryBarrier"),所以 Java 采用了 Volatile 来代替 Explicit 的 MB。
C# 不同,它提供了 Explicit 的 MB。
我已经给你了一个MS的链接,http://msdn.microsoft.com/library/system.threading.thread.memorybarrier.aspx
里面的话已经清楚解释了,MB的作用。
3)-----------------------------------------------------
当朝毛太祖说过"大乱才能大治" .. 访问完后还得释放这个锁。
--------------------------------------------------------
我和你的讨论都是围绕着 “Compaq Alpha SMP机器可能会即使有显式的memoryBarrier下,还是会有内存和cache的同步问题”。
而你总是把 lock 撤进来,显然你再次证明了你并不了解 MB。
我现在谈谈 lock:
lock 是同步多线程的共享数据的方法。
lock 是高级语言函数,它可能由几十或几百个 instruction 来实现,而其中肯定没有 MB instruction.
如果有就不会出现 MS 的解释 : http://msdn.microsoft.com/library/system.threading.thread.memorybarrier.aspx
也就是不会有 "Double-Checked Locking is Broken" 中 Volatile 的出现。
记住高级语言中,如果不是 asm (...),不等于一个 instruction。
例如 p = y (在 MIPSR3000 中) 对应着4个 instructions :
- &y => regh 取 y 地址,
- *regh => regi 取 y 值,
- &p => regj 取 p 地址,
- regi => regj 讲 y 值 付给 p 地址
所以,如果乱序,没法保证结果。
你说 lock 在这里有什么用 ????????????
4)-----------------------------------------------------
弱弱地问一句:
P1中的Thread1就不能被OS挂起,
而转去执行Thread3啊4的指令.
当然这时P2里面的thread 2可能正欢快的运行着。
既然是多线程,就就要这种thread1被人家3踢掉,
thread2正粉抹登场的场景考虑到吧。
除非你是用什么 non preemptive operation system.
--------------------------------------------------------
不明白你要讲什么,代码0是典型的“异步线程”。
Thread1 被挂起不挂起是都不影响 Thread2。
5)-----------------------------------------------------
感觉synchronised等高级 函数模块没有MB。要想MB怎么办,只能搞搞c/cc++或 M$ .NET或等x86 的高级智能判断机制了。
感觉高级函数模块模块是左手,MB 是 底层 instruction是右手。
左手碰不了右手,不能上下其手.我等做程序还不能觉得左手右手冗余,得学会容忍。
--------------------------------------------------------
MS的也有显示的MB。
虽然java中没考虑 Explicit的MB,但是提供了替补方案:Volatile
最后,既然你看了wiki为什么不看wiki的引用?
IBM的报告"Memory Barriers: a Hardware View for Software Hackers"
http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2009.04.05a.pdf
看过之后就会明白什么是MB了。
期待你倒空你的杯。 |
|