java内存模型的架构_java内存模型和内存结构

java内存模型说的是多线程,网上可能会有写误导,并不是什么堆、栈、方法区,很多人都会搞混。说白了就是多线程中主线程和本地线程之间的一个数据可见性问题。

jmm:java内存模型;jvm:java内存结构

先看看多线程特性:

1、原子性:保证数据一致性和安全性

2、可见性:保证主线程中的共享变量进行修改后,本地线程能第一时间知道,这就是可见性,下面会配图和代码进行说明

3、有序性:jvm的一个重排序,提高线程的运行效率的

下面来看看java内存模型,代码很简单

packagecom.springboot;/*** @Title: Java内存模型

* @Description:

*@author: sunxuesong@hztianque.com

* @date: Created in 9:18 2019/8/4

* @Modifired by:*/

public class Thread001 extendsThread {private boolean flag = true;/*** 子线程*/@Overridepublic voidrun() {

System.out.println("线程开始..");while(flag) {

}

System.out.println("线程结束..");

}public void setFlag(booleanflag) {this.flag =flag;

}/*** 主线程

*@paramargs

*@throwsInterruptedException*/

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

Thread001 thread001= newThread001();

thread001.start();

Thread.sleep(3000);

thread001.setFlag(false);

System.out.println("flag已经改为false");

Thread.sleep(1000);

System.out.println("flag:" +thread001.flag);

}

}

结果:

ce5278b3aac521769fd271501099af06.png

可以看到线程进入了死循环,主线程明明已经修改了值为false但是子线程就是看不见,这就是可见性的问题。

怎么修改呢?其实很简单只需要在主线程中的flag变量前面加一个关键字,下面在看看结果:

00a7a1668aea0ec7987dee490edb26cf.png

加了关键字之后三秒后直接跳出死循环,这个关键字volatile可以保证当主线程中的值刷新了之后会立马通知到子线程。

但是volatile只能保证数据的可见性,不能保证原子性。延伸一点知识volatile和synchronize区别:

volatile比synchronize性能上要好很多,但是不能保证数据原子性。

synchronize性能上比volatile差很多,因为他在并发情况下只能有一个线程去执行,但是可以保证数据的原子性。

下面说一下Java的内存结构:jvm

jvm主要结构有方法区、堆、栈

方法区:加了static关键字的都是放在方法区中,它是存放在永久区中是不会被垃圾回收机制进行回收的,所以static关键字要慎用(又称为永久区),当class文件被加载就会被初始化

堆:通过关键字new出来的对象都是放在堆内存中,垃圾回收也是针对堆进行

栈和本地方法区:局部变量和类的方法,代码运行完毕自动释放内存,每个线程都是私有的,不会共享,也不会产生线程安全问题

下面用代码对方法区就行说明:很有趣的代码

public classTest001 {private int count = 0;/*** 毫无疑问结果是2

*@paramargs*/

public static voidmain(String[] args) {

Test001 test001= newTest001();++test001.count;++test001.count;

System.out.println(test001.count);

}

}

再来看一个代码:

private static int count = 0;

/*** 结果也是2

* 因为static修饰的变量它存放在方法区中,是被所有线程所共享的,或者说是jvm中全局的变量

* 不要定义太多的常量,有可能会出现内存溢出的情况,这也是jvm内存调优的一种方式,但是主要调优策略是在堆中,不是在方法区

* private static Test001 test003 = new Test001();这也是存放在方法区中,不要误解,凡是加了static都是存放在方法区中

*@paramargs*/

public static voidmain(String[] args) {

Test001 test001= newTest001();

Test001 test002= newTest001();++test001.count;++test002.count;

System.out.println(test001.count);

}

jvm的内存结构就是这样子的了,切记内存模型和内存结构不要混淆,下节说一下jvm的垃圾回收机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值