——-volatile关键字

  1. public class volatileThread extends Thread{
  2. //定义成员变量
  3. private boolean flag = false;
  4. public boolean isFlag(){return flag;}
  5. @Override
  6. public void run(){
  7. try{
  8. Thread.sleep(1000)
  9. }catch(interruptedException e){
  10. e.printStackTrace();
  11. }
  12. //将flag的值更改为true
  13. this.flag = true;
  14. System.out.println("flag="+ flag);
  15. }
  16. }
  17. public class VolatileThreadDemo{
  18. public static void main(String[] args){
  19. //创建colatileThreead线程对象
  20. VolatileThread volatileThread = new VolatileThread()'
  21. volatileThread.start();
  22. //main方法
  23. while(true){
  24. if(volatileThread.isFlag())
  25. System.out.println("执行了====")
  26. }
  27. }
  28. }

image.png
线程中已经将flag设置为true,但是main()方法中始终没有读到,从而没有打印

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

1.VolatileThread线程从主内存读取到数据放入其对应的工作内存
2.将flag的值更改为true,但是这个时候flag的值还没有写会主内存
3.此时main方法读取到了flag的值为false
4.当VolatileThread线程将flag的值写回去后,但是main函数里面的while(true)调用的是系统比较底层的代码,速度快,快到没有时间去读取内存中的值所以while(true)读取到的值一致是false(如果有一个时刻main线程从主内存中读取到了主内存flag的最新值,那么if语句就可以执行,main线程何时从主内存中读取对新的值,我们无法控制)

解决问题:
加速

  1. //mian(方法)
  2. while(true){
  3. synchronized(volatileThread){
  4. if(volatileThread.isFlag()){
  5. System.out.println("执行了=====");
  6. }
  7. }
  8. }

某一个线程进入synchronized代码块前后,执行过程如下
a.线程获得锁
b.清空工作内存
c.从主内存拷贝共享变量最新的值到工作内存成为副本
d.执行代码
e.将新修改后的副本的值刷新回主内存中
f.线程释放锁

volatile关键字
使用volatile关键字:

  1. private volatile boolean flag;

工作原理:
image.png
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修饰成员变量,说明这个成员变量是属于类的,这个成员变量称为类变量或者静态成员变量,直接用类名访问即可,因为类只有一个,所以静态成员变量在内存区域也只存在一份,所有的对象都可以共享这个变量
定义格式:

  1. 修饰符 static 数据类型 变量名=初始值;

静态成员变量的访问:
格式:
类名.静态变量
实例变量及其访问:
无static修饰的成员变量属于每个对象的,这个成员变量叫做实例变量,之前我们写成员变量就是实例成员变量。
需要注意的是:实例成员变量属于每个对象,必须创建类的对象才可以访问
格式:
对象.实例成员变量
静态方法及其访问:
有static修饰成员方法,说明这个成员方法是属于类的,这个方法称为类方法或者静态方法,直接用类名访问即可,因为类只有一个,所有静态方法在内存区域也只存在一份,所有的对象都可以共享这个方法
与静态成员变量一样,静态方法也是直接通过类名.方法名称即可访问

——-this关键字

用于普通的gettter与setter方法
this出现在实例方法中,谁调用这个方法(哪个对象调用这个方法),this就代表谁
用于构造器中
this出现在构造器中,代表构造器正在初始化的那个对象

——-super关键字

——-extends关键字