【多线程和并发】简述Java的内存模型

它和JVM内存模型不一样

Java内存模型主要分为两块,一块为主内存,一块为工作内存。

Java内存模型规定所有的变量都在存放在主内存当中,每个线程都有自己独立的工作内存。线程对变量的所有操作都必须在工作内存当中进行,而不能直接对主内存进行操作,并且每个线程都不能访问其它线程的工作内存。

 

Java内存模型的Volatile关键字和原子性、可见性、有序性和happens-before关系。

一、volatile关键字

二、要想并发程序正确的执行,必须要保证原子性、可见性以及有序性。只要有一个没有被保证,就有可能导致程序运行不正确

1.原子性:即一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。通过synchronized和Lock实现“可见性”。

分析以下哪些操作时原子性操作。

x = 10;      //语句1
y = x;        //语句2
x++;          //语句3
x = x + 1;  //语句4

特别注意:在Java中,只有对除long和double外的基本类型的赋值(如 int  a = 1)或者读取操作才是院子的。还要给long或double加上volatile,操作就是原子的了。

语句1是原子性操作,其他三个都不是。

语句2其实包含了2个操作,首先读取x的值,然后把x的值写入工作内存,虽然读取x的值以及将x的值写入工作内存这个2个操作都是原子性操作,但是合起来就不是原子性操作了。

同样的,x++和x = x + 1包括三个操作,读取x的值,进行+1操作,写入新的值。

 

2.可见性:可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改得到的值。通过synchronized和Lock和volatile实现“可见性”。

3.有序性:即程序执行的顺序按照代码的先后顺序执行。

我的理解就是一顿程序代码的执行在单个线程中看起来是有序的。这个应该是程序看起来执行的顺序是按照代码顺序执行的,因为虚拟机可能会对程序大地吗进行指令重排序。虽然进行重排序,但是最终执行的结果是与程序顺序执行的结果一致的,它只会对不存在数据依赖性的指令进行重排序。因此,在单个线程中农,程序执行看起来是有序执行的。事实上,这个规则用来保证程序在单线程中执行结果的正确性,但无法保证程序在多线程中执行的正确性。

三、happens-before原则(先行发生原则)

  • 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
  • 锁定规则:一个unLock操作先行发生于后面对同一个锁的lock操作
  • volatile遍历规则:对一个变量的写操作先行发生于后面对这个变量的读操作
  • 传递规则:如果 操作ABC,A先行发生于B, B先行发生于C,那么A先行发生于C
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作
  • 线程中断规则:对线程interrupt方法的调用先行发生于被中断线程的代码检测到中断事件的发生
  • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
  • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始。

你可能感兴趣的:(多线程和并发)