——-volatile关键字
public class volatileThread extends Thread{//定义成员变量private boolean flag = false;public boolean isFlag(){return flag;}@Overridepublic void run(){try{Thread.sleep(1000)}catch(interruptedException e){e.printStackTrace();}//将flag的值更改为truethis.flag = true;System.out.println("flag="+ flag);}}public class VolatileThreadDemo{public static void main(String[] args){//创建colatileThreead线程对象VolatileThread volatileThread = new VolatileThread()'volatileThread.start();//main方法while(true){if(volatileThread.isFlag())System.out.println("执行了====")}}}

线程中已经将flag设置为true,但是main()方法中始终没有读到,从而没有打印
JMM**
JMM(java Memory Model) java内存模型,是java虚拟机规范中所定义的一种内存模型
Java内存模型描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取变量这样的底层细节
所有的共享变量都存储于主内存,这里所说的变量指的是实例变量和类变量,不包含局部变量,因为局部变量是线程私有的,因此不存在竞争问题,每一个线程还存在自己的工作内存,线程的工作内存,保留了被线程使用的变量的工作副本,线程堆变量的所有的操作(读,取)都必须在工作内存中完成,而不能直接读写主内存中的变量,不同线程之间也不能直接访问对方工作内存中的变量,线程间变量的值的传递需要通过主内存完成

1.VolatileThread线程从主内存读取到数据放入其对应的工作内存
2.将flag的值更改为true,但是这个时候flag的值还没有写会主内存
3.此时main方法读取到了flag的值为false
4.当VolatileThread线程将flag的值写回去后,但是main函数里面的while(true)调用的是系统比较底层的代码,速度快,快到没有时间去读取内存中的值所以while(true)读取到的值一致是false(如果有一个时刻main线程从主内存中读取到了主内存flag的最新值,那么if语句就可以执行,main线程何时从主内存中读取对新的值,我们无法控制)
解决问题:
加速
//mian(方法)while(true){synchronized(volatileThread){if(volatileThread.isFlag()){System.out.println("执行了=====");}}}
某一个线程进入synchronized代码块前后,执行过程如下
a.线程获得锁
b.清空工作内存
c.从主内存拷贝共享变量最新的值到工作内存成为副本
d.执行代码
e.将新修改后的副本的值刷新回主内存中
f.线程释放锁
volatile关键字
使用volatile关键字:
private volatile boolean flag;
工作原理:
1.Volatile Thread 线程从主内存读取到数据放入其对应的工作内存
2.将flag的值更改为true,但是这个时候flag的值还没有写回主内存
3.此时main方法读取到了flag的值为false
4.当Volatile Thread 线程将flag的值写回去后,失效其他线程对此变量副本
5.再次对flag进行操作的时候线程会从主内存读取最新的值,放入到工作内存中
总结:
volatile保证不同线程对共享变量操作的可见性,也就是说一个献策韩国修改了volatile修饰的变量,当修改写会主内存时,另外一个线程立即看到最新的值,但是volatile不保证原子性
volatile和synchronized
volatile只能修饰实例变量和类变量,而synchronized可以修饰方法,以及代码块
volatile保证数据的可见性,但是不保证原子性(多线程进行写操作,不保证线程安全);而synchronized是一种排他(互斥)的机制**
——-static关键字
定义格式和使用:
static是静态的意思,static可以修饰成员变量或作者修饰方法
静态变量及其访问:
有static修饰成员变量,说明这个成员变量是属于类的,这个成员变量称为类变量或者静态成员变量,直接用类名访问即可,因为类只有一个,所以静态成员变量在内存区域也只存在一份,所有的对象都可以共享这个变量
定义格式:
修饰符 static 数据类型 变量名=初始值;
静态成员变量的访问:
格式:
类名.静态变量
实例变量及其访问:
无static修饰的成员变量属于每个对象的,这个成员变量叫做实例变量,之前我们写成员变量就是实例成员变量。
需要注意的是:实例成员变量属于每个对象,必须创建类的对象才可以访问
格式:
对象.实例成员变量
静态方法及其访问:
有static修饰成员方法,说明这个成员方法是属于类的,这个方法称为类方法或者静态方法,直接用类名访问即可,因为类只有一个,所有静态方法在内存区域也只存在一份,所有的对象都可以共享这个方法
与静态成员变量一样,静态方法也是直接通过类名.方法名称即可访问
——-this关键字
用于普通的gettter与setter方法
this出现在实例方法中,谁调用这个方法(哪个对象调用这个方法),this就代表谁
用于构造器中
this出现在构造器中,代表构造器正在初始化的那个对象
