并发与并行的概念:
并发:一段时间内(假设只有一个CPU)执行多个线程,多个线程时按顺序执行
并行:同个时间点上,多个线程同时执行(多个CPU)
什么是并发编程?
在现代互联网的应用中,会出现多个请求同时对共享资源的访问情况,例如在买票,秒杀与抢购的场景中
此时就会出现线程安全的问题,并发编程就是通过编程控制多个线程依次执行防止线程安全的问题出现
并发问题产生的根本原因
多核CPU的处理
基于java的内存模型
JMM
JMM全称Java Memory Model表示Java内存模型,是java虚拟机中所进行规范的
java内存模型中规定所有的变量都存储在工作内存中,所有的线程共享工作内存中的变量
每个线程都会有自己私有的工作内存,线程会将工作内存中的共享变量读取到工作内存中作为缓存
并发编程解决的核心问题
可见性
可见性指的是线程在对共享变量进行修改之后,其他线程时能够立即知道
现在的多核CPU的处理中单个线程对共享变量进行修改后,其他的线程是不可见的
有序性
有序性是指的代码运行的顺序是按照的编写的顺序运行的
在代码编译运行的过程中,CPU为了提高性能,可能会打乱代码原来的编写顺序,比如需要读取一个读取时间较长的变量时,可能会跳过它去读取速度较快的变量
这是由于CPU的读等待机制造成的,CPU在读取一个读时间长的变量时会去同时读取其他的变量
原子性
原子性指的是操作的原子性,在多个指令操作同时进行时应该保证这多条命令的一致性执行
比如说"i++"这个操作是在高级语言中是一条编程指令,但实际上在CPU执行的时候可以拆分为三条CPU的执行指令,分别是从主内存中读取变量i的值,在工作内存中对变量的值进行操作,然后在对主内存中的值进行更新
如果此时多核的CPU支持线程切换的调度,则会导致"i++"这一条命令还没有执行完成就进行了线程的切换,导致出现的线程安全问题
小结
可见性的问题是由缓存导致的,有序性的问题是由编译导致的,原子性的问题是由线程切换导致的
三个问题出发点都是的为了的提高程序的性能,这与并发程序编写的目的是一致的