发表于: 2017-09-25 22:10:14

1 939


今天完成的:

整理业务关系的,设计前台方案,通过后台方案评审

收获:

为何wait需要在同步代码块中调用                                                  

wait是让使用wait方法的对象等待,暂时先把对象锁给让出来,给其它持有该锁的对象用,其它对象用完后再告知(notify)等待的那个对象可以继续执行了,因此,只有在synchronized块中才有意义。

指令重排序

public void ReorderingDemo() throws InterruptedException {
/**
    *@Author hfismyangel@163.com
    *@Description:指令重排序
    *@Date: 23:19 2017/9/25
    * @param
    */
   for (int i = 0; i < 100; i++) {
x = y = a = b = 0;
       Thread one = new Thread() {
public void run() {
a = 1;
               x = b;
           }
};
       Thread two = new Thread() {
public void run() {
b = 1;
               y = a;
           }
};
       one.start();
       two.start();
       one.join();
       two.join();
       System.out.println(x + " " + y);
   }
}

输出的结果可能是0.1,1.0,1,1,极端情况产生0,0。其中的操作可能是cpu高速缓存计算的数据没有及时刷新到主存中。

Happens-before法则

Java存储模型有一个happens-before原则,就是如果动作B要看到动作A的执行结果(无论A/B是否在同一个线程里面执行),那么A/B就需要满足happens-before关系。

在介绍happens-before法则之前介绍一个概念:JMM动作(Java Memeory Model Action),Java存储模型动作。一个动作(Action)包括:变量的读写、监视器加锁和释放锁、线程的start()和join()。后面还会提到锁的的。

happens-before完整规则:

(1)同一个线程中的每个Action都happens-before于出现在其后的任何一个Action。

(2)对一个监视器的解锁happens-before于每一个后续对同一个监视器的加锁。

(3)对volatile字段的写入操作happens-before于每一个后续的同一个字段的读操作。

(4)Thread.start()的调用会happens-before于启动线程里面的动作。

(5)Thread中的所有动作都happens-before于其他线程检查到此线程结束或者Thread.join()中返回或者Thread.isAlive()==false。

(6)一个线程A调用另一个另一个线程B的interrupt()都happens-before于线程A发现B被A中断(B抛出异常或者A检测到B的isInterrupted()或者interrupted())。

(7)一个对象构造函数的结束happens-before与该对象的finalizer的开始

(8)如果A动作happens-before于B动作,而B动作happens-before与C动作,那么A动作happens-before于C动作。

Volatile语义

volatile拥有可见性而不拥有原子性

(1)Java 存储模型不会对valatile指令的操作进行重排序:这个保证对volatile变量的操作时按照指令的出现顺序执行的。

(2)volatile变量不会被缓存在寄存器中(只有拥有线程可见)或者其他对CPU不可见的地方,每次总是从主存中读取volatile变量的结果。也就是说对于volatile变量的修改,其它线程总是可见的,并且不是使用自己线程栈内部的变量。也就是在happens-before法则中,对一个valatile变量的写操作后,其后的任何读操作理解可见此写操作的结果。

计划:

搭建开发环境,准备coding


返回列表 返回列表
评论

    分享到