概念介绍
单线程: 例如单车道上车辆有序前行
多线程: 例如多车道上车辆前行(速度会远远大于单线程)
优势:速度快
劣势:各个马路上会存在 加塞 情况,所以反而会导致 堵车 ,影响效率更慢
解决“加塞”问题
线程安全问题
单线程安全,多线程不安全问题主要有以下两个方面
1)原子性,有些操作并不是原子性所以导致线程不安全
原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
原子操作:即不会被线程调度机制打断的操作,没有上下文切换。
i = 0; // 基本数据类型变量的赋值属于原子操作。
i++; // 包含三个操作。读取i的值,i进行+1,将值赋值给i(不是原子操作)
i = j; // 读取j的值,赋值给i(不是原子操作)
i = i + 1; // 包含三个操作。读取i的值,i进行+1,将值赋值给i(不是原子操作)
2)可见性:指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
多个线程访问同一个变量,某个线程在修改值后,并没有直接将值刷新到内存中,而是刷新到自己的缓存区里。 所以导致另外线程去访问变量时,访问的还是原先值。
解决方案可以使用synchronize和lock
活跃性问题
(1)死锁
死锁是指多个线程因为环形的等待锁的关系而永远的阻塞下去
(2)活锁
死锁是两个线程都在等待对方释放锁导致阻塞。而活锁的意思是线程没有阻塞,还活着呢。
(3)饥饿
如果一个线程无其他异常却迟迟不能继续运行,那基本是处于饥饿状态了。
常见有几种场景:
- 高优先级的线程一直在运行消耗CPU,所有的低优先级线程一直处于等待;
- 一些线程被永久堵塞在一个等待进入同步块的状态,而其他线程总是能在它之前持续地对该同步块进行访问;
性能问题
创建线程是直接向系统申请资源的,对操作系统来说创建一个线程的代价是十分昂贵的,需要给它分配内存、列入调度等。
线程创建完之后,还会遇到线程上下文切换。