学习笔记 变量定义在静态块输出之后 不能输出的问题

 


public class Test
{
    static
    {
        i=0;
        System.out.println(i);//这句编译器会报错:Cannot reference a field before it is defined(非法向前应用)
    }

    static int i=3;

     public static void main(String[] args) {
  
    } 
}

}为何在静态块时输出时会报错的原因。其实这个时候i已经分配好内存并赋值为3了,由下面代码可以证明。先运行实例化对象,再输出类对象的参数成功。

public class statictest {         
    static{ 
        b=3;
      } 

    static statictest st = new statictest(); 
        
    statictest()  {          
        system.out.println(b);     
    }         

    public static int b=10;   
      
    public static void main(String[] args) {
  
} 

}


load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。

  • assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。

问题在于java内存模型,不允许一个工作内存中直接使用一个未被初始化的变量,当开始b申请了空间初始化为0后,在类加载的初始化阶段,顺序执行静态语句时候,已经将b=0从主内存复制到了工作内存,执行b=3 (修改工作内存),不允许一个线程丢弃它的最近的assign操作,即变量在工作内存中改变了之后必须把该变化同步回主内存。但是没有完成提交到主内存完成assign和从主内存读load操作,故输出错误。但是在执行内实例化前,会将工作内存中所有数据同步到主内存,故满足了规则一个新的变量只能在主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量,换句话说,就是对一个变量实施use、store操作之前,必须先执行过了assign和load操作。

8种基本操作规则:

  • 不允许read和load、store和write操作之一单独出现,即不允许一个变量从主内存读取了但工作内存不接受,或者从工作内存发起回写了但主内存不接受的情况出现。
  • 不允许一个线程丢弃它的最近的assign操作,即变量在工作内存中改变了之后必须把该变化同步回主内存。
  • 不允许一个线程无原因地(没有发生过任何assign操作)把数据从线程的工作内存同步回主内存中。
    • 一个新的变量只能在主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量,换句话说,就是对一个变量实施use、store操作之前,必须先执行过了assign和load操作。
  • 一个新的变量只能在主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量,换句话说,就是对一个变量实施use、store操作之前,必须先执行过了assign和load操作。
  • 一个变量在同一个时刻只允许一条线程对其进行lock操作,但lock操作可以被同一条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。
  • 如果对一个变量执行lock操作,那将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值。
  • 如果一个变量事先没有被lock操作锁定,那就不允许对它执行unlock操作,也不允许去unlock一个被其他线程锁定住的变量。
  • 对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store、write操作)。

这8种内存访问操作以及上述规则限定,再加上稍后介绍的对volatile的一些特殊规定,就已经完全确定了Java程序中哪些内存访问操作在并发下是安全的。由于这种定义相当严谨但又十分烦琐,实践起来很麻烦,所以在后文将介绍这种定义的一个等效判断原则——先行发生原则,用来确定一个访问在并发环境下是否安全。

注: 
基于理解难度和严谨性考虑,最新的JSR-133文档中,已经放弃采用这8种操作去定义Java内存模型的访问协议了(仅是描述方式改变了,Java内存模型并没有改变)。

 

发布了34 篇原创文章 · 获赞 1 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章