本文共 1526 字,大约阅读时间需要 5 分钟。
- 锁
- 锁的分类
- 偏向锁
- 轻量级锁
- 死锁
- 场景
- 两个线程分别占有另一线程需要的资源,等待对方互相释放锁,或是某一线程释放是发生异常没释放掉,导致系统不可用的一个现象。
- 分析
- jps 查看java进程的pid
- jstack pid dump哪个线程出现了问题
- 避免死锁的方法
- 避免一个线程同时获取多个锁
- 避免一个线程在锁内同时占有多个资源,经理保证每个锁只使用一个资源
- 尝试使用定时锁,如 lock.tryLock(timeOut)来替代使用内部锁
- 对于数据库锁,加锁与解锁必须在同一个connection连接内,否则会出现解锁失败的情况
- synchronized的使用与原理
- 大致介绍一下它属于java并发编程中常见的一个锁,属于重量级锁。
- 使用
- 加在普通方法上 锁为当前的实例对象
- 加在静态方法上,锁为当前类的class对象
- 同步方法块上,锁时括号内配置的对象
- 原理
- 当一个线程试图操作同步代码块时,必须先获取锁,同时在退出或抛出异常时必须释放锁。从jvm层次来看,使用Monitor对象来控制同步方法,这里会出现moniterenter(开始)和monitorexit(结束)指令。线程执行到开始指令会尝试回去moniter所有权即获取对象的锁。
- Lock
Lock lock = new ReentrantLock();//放在try外面lock.lock();try { }finally { }
- 与synchronized不同
- 尝试非阻塞性的获取
- 超时获取
- 被中断的获取
- 常见方法
- 自定义同步组件
- 静态内部类Sync extends AbstractQueuedSynchronizer
- implements Lock
- lock –> sync.xxx()
- 线程获取锁失败后会放入同步队列中等待
- 分析同步器是如何完成线程同步的
- 同步队列
- 节点
- 前驱 后置引用
- FIFO
- 设置首节点
- 设置尾节点
- 独占式同步状态获取与释放
- 简单说,在获取同步状态时,同步器维护了一个队列,获取失败的线程会进入队列并在队列中自旋,移出队列或停止自旋的条件时前驱节点为头节点,且成功获取了同步状态,释放同步状态时需要调用方法释放状态,唤醒头节点的后置节点。
- 共享式同步状态获取与释放
- 在同一个时刻能有多个线程获取到同步状态
- tryAquiredShared()
- tryReleaseShared()
- 独占式超时获取同步状态
- 会有一个等待时间,在指定时间内没获取到会从等待的逻辑中返回
- 自定义同步器
- 重入锁
- 支持一个线程对资源重复加锁
- synchronized 支持隐式重入
- 公平与否
- 在绝对时间上,先对锁进行获取的请求一定先满足那么就是公平的 先到先得FIFO
- 实现
- 指的是任意线程在获取锁之后重新获取该锁而不会被阻塞
- 公平锁保证了FIFO其代价是进行了大量的线程切换
- 非公平锁虽然可能会造成线程饥饿但是极少切换线程
- 读写锁
转载地址:http://qqiii.baihongyu.com/