锁与并发
一.安全锁存在的理由:锁的基本概念和实现
1.基本作用:保护临界区资源不会被多个线程同时访问而受到破坏
2.线程安全:在多线程的环境下,访问目标对象的状态始终保持一致
3.synchronize 关键字保证了多线程环境下对象内部数据的一致性,但影响的效率
4.对象头和锁:在 java 虚拟机的实现中每个对象都有一个对象头,保存对象的系统信息
对象头中有一个称为 Mark Work 的部分,是实现锁的关键,一个对象是否占用锁,占用
哪个锁,就记录在 Mark Work 中。Mark Work 是一个多功能数据区
二.锁在java 虚拟机中的实现和优化
1.偏向锁:如果程序没有竞争,则取消之前已经取得锁的线程同步操作。使用
-XX:+UseBiasedLocking 可以设置启用偏向锁。
偏向锁在竞争少的情况下,对系统性能有一定的帮助。
偏向锁在锁竞争激烈的场合没有太强的优化效果,因为竞争会导致持有锁的线程不停的切换,
锁也很难一直保持偏向模式,此时,使用偏向锁还会影响系统性能。在竞争激烈的场合可以考虑
禁用偏向锁 -XX:-UseBiasedLocking
2.轻量级锁:如果偏向锁失败,java虚拟机会让线程申请轻量级锁,轻量级锁在java虚拟机内部,使用一个
BasicObjectLock 的对象实现,这个对象内部由一个 BasicLock 对象和一个持有该锁的 java 对象指针
组成。BasicObjectLock 放置在java 栈的栈帧中。在 BasicLock 对象内部还维护着 displaceed_header 字段
它用于备份对象头部的 Mark Work
如果加锁失败,那么轻量级 锁就有可能被膨胀为重量级锁
3.锁膨胀:当轻量级锁失败,虚拟机就会使用重量级锁
4.自旋锁:锁膨胀后,线程在操作系统层面很可能被挂起,这样线程上下文切换的性能损失就比较大,为了避免
线程被挂起,使用自旋锁就是一种有效的方式。但是在 JDK1.7 中,自旋锁的参数被取消,虚拟机不在支持用户
配置自旋锁,自旋锁由虚拟机执行,并自行调整次数
5.锁消除:去除不可能存在共享资源竞争的锁
三.锁在应用层的优化思路
1.减少锁持有的时间
2.减小锁粒度
3.锁分离
4.锁粗化
四.无锁
1.CAS
2.原子操作
3.LongAddr
五.java 内存模型
1.原子性
2.有序性
3.可见性
4.Happens-Befor原则