在多线程这一系列中,不去探究内存模型的底层缓存
在现代多核处理器中,每一个处理器都有本身的缓存,按期的与主内存进行协调;安全
想要确保每一个处理器在任意时刻知道其余处理器正在进行的工做,将须要很大的开销;且一般是不必的多线程
咱们只有在须要跨线程共享数据时,才须要知道信息;而在JAVA中就是经过正确的同步来实现app
以下:判断输出的值将十分困难spa
public class PossibleReordering { static int x = 0, y = 0; static int a = 0, b = 0; /** * 判断输出值将会很是困难: * 1:多线程之间的切换,致使可能的输出值:(0,1)(1,0)(1,1) * 2.指令重排序:one线程如a=1和x=b之间重排序,x=b(0),而后other线程被调度执行y=a(0),将致使(0,0) */ public static void main(String[] args) throws InterruptedException { Thread one = new Thread(new Runnable() { public void run() { a = 1; x = b; } }); Thread other = new Thread(new Runnable() { public void run() { b = 1; y = a; } }); one.start(); other.start(); one.join(); other.join(); System.out.println("( " + x + "," + y + ")"); } }
偏序关系:反对称、自反和传递属性;可是对于任意的两个元素A和B,并不必定知足A偏向B或B偏向A的关系线程
如:A和B之间我更偏向B,可是我不必明确的作出选择code
JMM为程序中全部的操做定义了一个偏序关系,称之为Happens-Before;要想保证执行B操做的线程看到执行A操做的线程的结果,不管AB是否在同一线程,必须知足Happens-Before关系,不然JVM就会对其重排序对象
如:加锁操做,就能够预知执行顺序,多个线程之间就符合Happens-Before,不加锁则没法判断线程之间的调度,blog
真正缘由:发布一个共享对象 和 在另外一个线程中访问该对象之间没有Happens-Before关系;因为指令重排序,致使对象没有正确构建则被发布排序
public class UnsafeLazyInitialization { private static Resource resource; /** * 除了竟态条件问题检查后执行,还有不安全发布的问题 * 如:一个线程A进来,看到resource为null,则实例化并返回;另外一个线程B进来看到resource不为null直接返回 * 若是在线程A中对resource进行了修改,则可能在线程B中看不到resource的正确状态 */ public static Resource getInstance() { if (resource == null) resource = new Resource(); // unsafe publication return resource; } static class Resource { } }