我的理解,同步就是为了解决重排序的问题。内存屏障的意思就是程序正常读写内存时,遇到了happen before,就像遇到一堵墙同样,必须排队过去缓存
Synchronization has several aspects. The most well-understood is mutual exclusion -- only one thread can hold a monitor at once, so synchronizing on a monitor means that once one thread enters a synchronized block protected by a monitor, no other thread can enter a block protected by that monitor until the first thread exits the synchronized block.app
Synchronization有多种含义。最广为人知的是互斥————同一时刻一条线程只能持有一个监视器,所以能够在这个监视器上实现同步,这意味着,对于由一个监视器保护着的同步块,只要有一个线程进入,其它线程就进不去了,由于拿不到监视器。ui
But there is more to synchronization than mutual exclusion. Synchronization ensures that memory writes by a thread before or during a synchronized block are made visible in a predictable manner to other threads which synchronize on the same monitor. After we exit a synchronized block, we release the monitor, which has the effect of flushing the cache to main memory, so that writes made by this thread can be visible to other threads. Before we can enter a synchronized block, we acquire the monitor, which has the effect of invalidating the local processor cache so that variables will be reloaded from main memory. We will then be able to see all of the writes made visible by the previous release.this
但Synchronization并不止互斥。Synchronization能够确保可见性,在相同的监视器下,一条线程在同步块以前或当中向内存写入时,其它线程会看到这个写入。这是因为在离开同步块后,线程会释放这个监视器,而释放监视器会将缓存刷进主内存。在进入同步块以前,线程会获取监视器,而获取监视器会清空本地处理器缓存,这样变量值就会从主内存从新加载。这样的话,全部以前的写入都是可见的了。线程
Discussing this in terms of caches, it may sound as if these issues only affect multiprocessor machines. However, the reordering effects can be easily seen on a single processor. It is not possible, for example, for the compiler to move your code before an acquire or after a release. When we say that acquires and releases act on caches, we are using shorthand for a number of possible effects.code
以上是在有缓存的状况下讨论的,听起来好像只会发生在多核处理器中,可是,单核处理器中也很容易出现重排序。在获取监视器以前,以及释放监视器以后,编译器是不会移动代码的。这里只提到获取和释放二词,但实际上会有不少细节在其中的。orm
The new memory model semantics create a partial ordering on memory operations (read field, write field, lock, unlock) and other thread operations (start and join), where some actions are said to happen before other operations. When one action happens before another, the first is guaranteed to be ordered before and visible to the second. The rules of this ordering are as follows:排序
在新的内存模型语义下, 在内存操做(读、写、加锁、解锁),以及其余线程操做(启动、中止)时,会进行局部排序,这被称做happen before语义,一些操做会先于其余操做以前进行。当A操做happen before 操做B,则A会被强制排序在B前面,而且对B是可见的。其中排序规则以下:ip
Each action in a thread happens before every action in that thread that comes later in the program's order.内存
线程中每一个操做,happen before,此线程中以后的按序操做
An unlock on a monitor happens before every subsequent lock on that same monitor.
监视器的解锁,happen before,此监视器随后的加锁
A write to a volatile field happens before every subsequent read of that same volatile.
volatile字段的写入,happen before,此字段随后的读取
A call to start() on a thread happens before any actions in the started thread.
调用start(),happen before,所启动线程的每一个操做
All actions in a thread happen before any other thread successfully returns from a join() on that thread.
线程中全部操做,happen before,其它线程调用此线程的join()成功返回
This means that any memory operations which were visible to a thread before exiting a synchronized block are visible to any thread after it enters a synchronized block protected by the same monitor, since all the memory operations happen before the release, and the release happens before the acquire.
Happen before的语义意味着,同一个监视器保护着的同步块,对于一条线程,在该线程进入同步块以后、离开以前,任何对其可见的内存操做,对其余线程也是可见的。由于全部的内存操做 hapen before 监视器的释放,监视器的释放 happen before 监视器的获取。
简而言之,外面的能看到里面的。监视器的释放先于获取,解释了以上“而释放监视器会将缓存刷进主内存”,由于按时间顺序,写入主内存 --> 释放 --> 获取。
Another implication is that the following pattern, which some people use to force a memory barrier, doesn't work:
Synchronization的另外一个含义,是以以下的方式,制造一个内存屏障,虽然不少人这样用,但其实是错的:
synchronized (new Object()) {}
This is actually a no-op, and your compiler can remove it entirely, because the compiler knows that no other thread will synchronize on the same monitor. You have to set up a happens-before relationship for one thread to see the results of another.
以上其实是一个空操做no-operation,编译器会将synchronized彻底移除,由于这不是同一个监视器,其它线程不会在这里同步。为了看到一条线程对内存中数据的修改,你必须将它与其它线程设置happen-before关系,也就是要让这条线程先进入同步块。
Important Note: Note that it is important for both threads to synchronize on the same monitor in order to set up the happens-before relationship properly. It is not the case that everything visible to thread A when it synchronizes on object X becomes visible to thread B after it synchronizes on object Y. The release and acquire have to "match" (i.e., be performed on the same monitor) to have the right semantics. Otherwise, the code has a data race.
注意:为了合理的经过同步,让两条线程产生happen before关系,必须使用相同的监视器。