多线程编程的特点
- 同一份代码,可以有多个线程执行
——即可以在一个CPU核上面并发执行
——也可以在多个CPU核上并行执行 - 线程的执行默认是乱序的
——程序员不能假定执行次序 - 线程会共享数据(对象的变量)
——需要互斥 - 线程之间也需要合作(同步)
如何实现互斥?
锁
- 只有获得了锁的线程,才能对共享资源做操作,换句话说:进入临界区
对共享资源做完操作(即使发生异常),一定要释放锁!
锁是什么东西?
- “锁”本身如果是软件,也没法保证原子性!
——多个CPU对“锁”操作的时候也会出错 - 最底层需要硬件指令的支持
——TestAndSet
——Swap
设计“锁”需要考虑的问题
- 线程申请锁的时候,发现已经被别的线程持有,线程该怎么办?
- 1、继续尝试,无线循环
——时间片用完了,变成就绪状态,等待下次调度
——自旋锁 - 2、把线程放到阻塞队列中
可重入性
- 自旋锁无法重入
- 解决办法
——记录这个锁被谁持有
——记录重入的次数
线程之间的通信:wait/notify
线程之间的通信:join
JDK中常用的锁:可重入互斥锁
Lock lock = new ReentrantLock();
//获取锁
lock.lock();
try{
}finally{
//释放锁
lock.unlock();
}
JDK中常用的锁:信号量
在同一时刻,只能有三个线程获得锁(不是互斥的)
JDK常用的锁:Reader Writer
JDK常用的锁:CountDownLatch
JDK常用多的锁:CyclicBarrier
死锁
死锁的预防
- 每个线程申请锁的时候都按特定的次序
- 申请锁的时候加上timeout
-