概念:
并发:同时拥有两个或多个线程,如果程序在单核处理器上运行,多个线程将交替地换入或者换出内存,这些线程是同时“存在”的,每个线程都处于执行过程中的某个状态,如果运行在多核处理器上,此时,程序中的每个线程都将分配到一个处理器上,因此可以同时运行。
高并发:高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过保证系统能够并行处理很多请求。
并发和高并发的侧重点其实还是有一些细微的不同,在谈到并发时候,我们侧重于多个线程操作相同的资源,保证线程安全,合理利用资源。高并发是在系统运行的过程中短时间内遇到大量操作请求的情况,要求服务可以同时处理很多请求,提高程序性能。
高并发编程基础:
CPU多级缓存
为什么需要CPU cache : CPU的频率太快了,快到主存跟不上,这样在处理器时钟周期内,CPU常常要等待主存,浪费资源。所以cache出现,是为了缓解cpu和内存之间速度的不匹配问题(结构:cpu>cache>memory)
CPU缓存有什么意义
1)时间局限性:如果某个数据被访问,那么在不久的将来它很可能被再次访问;
2)空间局限性:如果某个数据被访问,那么与它相邻的数据很快也可能被访问;
缓存一致性协议(MESI)
用于保证多个CPU cache之间缓存共享数据的一致
乱序执行优化
处理器为提高运算速度而做出违背代码原有顺序的优化
Java内存模型:
Java虚拟机规范中试图定义一种Java内存模型来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致性的内存访问效果。
Java内存模型主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量的操作底层细节。此处的变量(Variables)与Java编程中的变量有所区别,它包括了实例字段,静态字段,和构成数组对象的元素,但不包括局部变量与方法参数,因为后者是线程私有的,不会被共享,自然不会出现竞争问题。
java内存模型 - 同步八种操作
关主内存和工作内存之间的具体的交互协议,即一个变量如何从主内存拷贝到工作内存,如何从工作内存同步回主内存之类的实现细节,Java内存模型定义了以下8种操作来完成,虚拟机实现时必须保证下面的每一种操作都是原子的、不可再分割的。
lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。
unlock(解锁):作用于主内存的变量,它把一个处于锁定状态之中的变量释放出来,释放出来后的变量可以被其他线程锁定。
read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便后面load动作使用。
load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放到工作内存的变量副本中。
use(使用):作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值得字节码指令时会执行这个操作。
assin(赋值):作用于工作内存的变量,它将一个执行字节码引擎接受到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
store(存储):作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用。
write(写入):作用于主内存的变量,它把store操作从工作内存得到的变量的值放入到主内存中去。
java内存模型 - 同步规则
不允许read和load、store和write操作之一单独出现。
不允许一个线程丢弃它的最近的assign操作,即变量变量在工作内存中改变了后必须把变化同步到主内存。
不允许一个线程无原因地把数据从线程的工作内存同步到主内存。
一个新的变量只能从主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化的变量。
一个变量在同一时刻只允许对其进行lock操作,但lock操作可以被同一个线程执行多次,多次执行后只有执行相同次数的unlock操作变量才会被解锁。
如果对一个变量执行lock操作,那将会清空工作内存中此变量的值,在执行引擎使用这个变量之前,需要重新执行load或assin初始化变量的值。
如果一个变量事先没有被lock操作锁定,那就不允许对它执行unlock操作,也不允许去unlock一个被其他线程锁定住的变量。
对一个变量执行unlock之前,必须先将此变量同步回主内存中。
(详情见JVM解析)...
并发的优势与风险