赞
踩
Java内存模型与Java内存结构不同,Java内存结构指的是jvm内存分区。Java内存模型描述的是多线程环境下原子性,可见性,有序性的规则和保障。
Java内存模型提供了主内存和工作内存两种抽象,主内存指的是共享区域 ,工作内存指的是线程私有工作空间。
当一个线程访问共享数据时,需要先将共享数据复制一份副本到线程的工作内存(类比操作系统中的高速缓存),然后在工作内存进行操作,最后再把工作内存数据覆盖到主内存。主内存和工作内存交互通过特定指令完成。
如下为并发内存模型图
多线程环境下原子性,可见性,有序性分别指的是
原子性:程序执行不会受到线程上下文切换的影响。
可见性:程序执行不会受到CPU缓存影响。
有序性:程序执行不会受到CPU指令并行优化的影响。
public class Test {
static boolean flag = true;
public static void main(String[] args) throws InterruptedException {
//3秒后线程无法停止
new Thread(()->{
while(flag){
}
}).start();
Thread.sleep(3000);
System.out.println("flag = false");
flag =false;
}
}
public class Test {
static boolean flag = true;
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
while(flag){
synchronized (Test.class){}
}
}).start();
Thread.sleep(3000);
System.out.println("flag = false");
flag =false;
}
}
public class Test {
static volatile boolean flag = true;
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
while(flag){
}
}).start();
Thread.sleep(3000);
System.out.println("flag = false");
flag =false;
}
}
public class Test { static volatile int a = 0; public static void main(String[] args) throws InterruptedException { new Thread(()->{ for(int i=0;i<100000;i++){ a++; } }).start(); new Thread(()->{ for(int i=0;i<100000;i++){ a--; } }).start(); Thread.sleep(1000); System.out.println(a); //不能保证a为0 } }
class Test{
int a = 0;
boolean flag = false;
public void f1() {
a = 1;
flag = true;
}
public void f2() {
if (flag) {
int i = a +1;
}
}
}
指令a 指令b
阶段1 阶段2 阶段3 阶段4 阶段5 阶段1 阶段2 阶段3 阶段4 阶段5
指令a
阶段1 阶段2 阶段3 阶段4 阶段5
指令b
阶段1 阶段2 阶段3 阶段4 阶段5
valatile int a = 0;
a++;
//写屏障
//读屏障
int b = a;
int b=1;
a++;
//写屏障
//以下操作在线程A中执行
i = 1;
//以下操作在线程B中执行
j = i;
//以下操作在线程C中执行
i = 2
使用内核线程实现
内核线程就是直接由操作系统内核支持的线程,通过内核完成线程的切换。
通过线程调度器来负责线程调度,即将线程任务分配到指定处理器。
在用户态,每个内核级线程会一 一对应一个轻量级进程,就是通常所说的用户级线程,多个用户级线程可以组成一个用户进程。
如下所示:p进程 LWP用户线程 KLT内核线程 Thread Scheduler 线程调度器
由于内核线程的支持,每个用户线程都是独立调度单位,即使有一个用户线程阻塞了,也不会影响当前进程其他线程执行。但是用户线程切换 创建 终止都要内核支持,内核与用户态切换代价较高。
Java就是使用内核线程实现的,无论是windows还是linux都是基于内核线程实现的。
使用用户线程实现
操作系统内核只能感知到用户进程,用户进程为操作系统内核的基本调度单位。
基于用户进程实现的用户线程,线程的创建 切换 销毁都是进程自己管理,与内核没有关系。因为操作系统只能把处理器资源分配到进程,那么线程的运行 阻塞 生命周期管理都要用户进程自己来实现。
内核不参与线程调度,因此线程的上下文切换开销比较小,但是实现起来非常复杂,而且当一个用户级线程阻塞整个进程都会阻塞,并发度不高。
混合模式实现
用户线程和内核线程使用M对N的映射来实现,兼顾两者的优点。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。