6、多线程
synchronized关键字与CAS机制
synchronized:悲观锁
CAS 机制:乐观锁
当程序的并发量比较高的时候用悲观锁
java当中有很多地方应用了CAS机制,比如说AtomicInteger等Atomic...系列以及Lock系列
CAS缺点:
- 在并发量比较高的时候会给cpu带来很大的压力
- 只能保证一个变量的原子性,不能保证一个代码块的原子性
- ABA问题
ABA问题解决方案:
加入变量的版本号,在Compare阶段不仅要比较期望值A和地址V中的实际值,还要比较变量的版本号是否一致。在Java当中,AtomicStampedReference类就实现了用版本号做比较的CAS机制。
volatile关键字:
Java内存模型简称JMM(Java Memory Model),是Java虚拟机所定义的一种抽象规范,用来屏蔽不同硬件和操作系统的内存访问差异,让java程序在各种平台下都能达到一致的内存访问效果。
同步锁synchronized虽然可以保证线程安全,但是对程序性能的影响太大了,有一种轻量级的解决办法,就是用volatile关键字
- volatile关键字可以保证变量的可见性但是并不能保证对其操作的原子性(比如对这个变量做++操作 i++)
- volatile关键字可以禁止指令重排序优化
在当前的Java内存模型下,线程可以把变量保存在工作内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。
要解决这个问题,只需要像在本程序中的这样,把该变量声明为volatile(不稳定的)即可,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。一般说来,多任务环境下各任务间共享的标志都应该加volatile修饰。
volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
线程与协程
image.png线程不同状态之间的转化是通过操作系统内核中的TCB(Thread Control Block)模块来改变线程的状态,这一过程需要耗费一定的CPU资源。
协程,英文Coroutines,是一种比线程更加轻量级的存在。正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程。最重要的是,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)。
这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。
image.png
image.png