网站开发 需要用到什么软件,seoul是什么国家,后端工资一般比前端高吗,医院网站建设合同范本一、背景
并发编程本质问题是#xff1a;CPU、内存以及IO三者之间的速度差异。CPU速度快于内存、内存访问速度又远远快于IO#xff0c;根据木桶理论#xff0c;程序性能取决于最慢的操作#xff0c;即IO操作。这样会出现CPU和内存交互时#xff0c;CPU性能无法被充分利用…一、背景
并发编程本质问题是CPU、内存以及IO三者之间的速度差异。CPU速度快于内存、内存访问速度又远远快于IO根据木桶理论程序性能取决于最慢的操作即IO操作。这样会出现CPU和内存交互时CPU性能无法被充分利用内存与IO交互时内存性能也存在部分损耗单方面提升CPU或内存的性能是无效的。为了提升CPU或内存的利用率需要平衡三者的速度差异计算机系统结构、操作系统以及编译程序都做出了贡献主要体现为
1. 计算机体系结构为CPU增加了缓存均衡和内存的速度差异
2. 操作系统增加了进程和线程便于分时复用CPU均衡CPU与IO设备的速度差异
3. 编译程序优化CPU指令的执行顺序使得缓存被更加合理的利用。上述方案虽然很大程度上解决了程序的性能问题但也带来了许多隐藏的并发问题主要为可见性问题、原子性问题以及有序性问题。
可见性问题 定义一个线程对共享变量的修改另外一个线程能够立刻看到即可见性 导致原因CPU缓存 详情解析在多CPU时代每个CPU都有自己的缓存当多个CPU缓存同一份共享变量的数据时线程A修改了共享变量但修改目前只在CPU的缓存生效其他CPU缓存还未来得及获取新修改的数据线程B读取共享变量读取的数据是老数据存在数据不一致问题。 原子性问题 定义一个或多个操作在CPU执行过程中不被中断的特性即原子性 导致原因多线程上下文切换 详情解析多线程底层执行是按照时间片来执行的进行任务切换时针对的是单个CPU指令仅能保证单个CPU指令的原子性。而高级语言的一条语句往往是由多个CPU指令完成。例如count 1至少需要三条指令 1. 首先将变量count加载到对应CPU的寄存器中; 2. 其次在寄存器中执行 1 操作 3. 最后将结果写入到内存中 若是线程A执行完指令1后切换到线程B来执行 count 1操作线程B操作后count为2但线程A中保存的count值仍是1导致最后的结果为2实际上应该为3。 Java中的原子操作有哪些
1. 除long和double之外的基本类型(int, byte, boolean, short, char, float)的赋值操作针对long操作直接拆分成两个32位的写入操作。
2. 所有引用reference的赋值操作
3. java.concurrent.Atomic.*包中所有类的原子操作。
原子操作 原子操作 原子操作【原子性对比】
synchronized不可中断锁适合竞争不激烈可读性好
Lock: 可中断多样化同步竞争激烈时能维持常态
Atomic: 竞争激烈时能维持常态比Lock性能好只能同步一个值有序性问题 定义有序性是指按照代码的先后顺序来执行但编译器为了优化性能可能会改变代码的执行顺序。例如i 1; j 2 变成 j 2; i 1 导致原因编译优化 详情解析在Java领域存在一个双重检查创建单例对象的场景创建对象JVM底层分为三个步骤 1. 分配内存空间 2. 在内存上初始化对象 3. 将对象地址赋值给实例变量 此时进行了编译优化将123变成了132。那么就会出现多线程访问时某些线程获取的对象为null出现空指针问题。 因此为了解决出现的可见性、原子性以及有序性问题Java给出了一套解决方案即Java Memory Model简称JMM。
二、Java内存模型
为了解决可见性和有序性直观上可以理解禁用缓存和编译优化但程序的性能就无法保证。理想方案是开发者按需禁用缓存和编译优化因此Java做了两个方面的工作
定义一种抽象计算机模型定义一系列规则来保证可见性和有序性。
2.1 定义
抽象计算机模型JMM定义了线程和主内存之间的抽象关系线程之间共享的变量存储在主内存中每个线程有一个私有的本地内存每个本地内存中存储了共享变量的副本。其中本地内存[工作内存]是一个抽象概念底层对应着缓存、寄存器以及硬件和编译器优化等。主内存和工作内存之间的规范为
所有的共享变量都存储于主内存这里的变量值是实例变量、类变量以及数组因为堆和方法区是线程共享的。局部变量属于线程私有不存在线程安全问题工作内存每一个线程有自己的工作内存工作内存中保留了被多个线程使用的变量的工作副本线程不能直接读写主内存中的变量 ① 只能操作自己的工作内存中的变量 ② 然后再同步到主内存中工作内存的屏蔽性不同线程之间不能直接访问对方工作内存中的变量线程之间的值传递需要通过主内存来完成。(可见性问题的罪魁祸首
一系列规则volatile、synchronized和final三个关键字以及六项Happens-Before规则。
2.2 规则
Happens-Before规则指的是前面一个操作结果对后续操作是可见的。下面为详细的规则
单线程规则一个线程中的每个操作happens-before于该线程的任意后续操作监视器锁规则(synchronized)对一个锁的解锁happens-before于随后对这个锁的加锁volatile变量规则对一个volatile修饰的变量的写happens-before于随后对这个变量的读传递性如果A happens-before B、 B happens-before C、则A happens-before C线程start启动规则主线程A启动子线程B后子线程B能够看到主线程在启动子线程B前的操作结果线程join()规则: 主线程A等待子线程B完成当子线程B完成后主线程能够看到子线程的操作结果。final规则: 通过final修饰变量告诉编译器着变量是不会发生改变的可以尽情优化。
三、总结
上述解决了可见性和有序性问题原子性问题通过互斥锁可以完美解决。