当前课程知识点:JAVA程序设计进阶 > 第三章 线程(下) > 3.5 锁优化 > Video
这一节我们将介绍
如何进行锁优化
那在java的线程安全的控制当中
我们有的时候必须加锁
那能不能使我们加锁的效率
更高一些呢
那锁优化的这种做法呢
是从JDK6.0版本开始的
它主要有这么几种这个
优化的这个方式
一种是自旋锁
另外一种是自适应锁
第三种是锁消除
第四种是锁粗化
最后一种是偏向锁
我们先看一下自旋锁
那自旋锁主要是
想解决什么样的问题呢
当我们有互斥同步
来去实现这种线程安全的时候
它存在的问题就是
我们挂起的线程和恢复的线程
都需要转入到操作系统的
内核态当中去完成
那这些会给我们的
系统的并发性能
带来很大的压力
那有没有些办法
能改善这种问题呢
那可以考虑使用自旋锁
也就是说如果我们的物理机上
有一个以上的处理器
能让两个或以上的线程
同时并行执行的话
我们就可以考虑
让后面请求锁的那个线程
稍等一会儿
也就是说不是说
它后面的线程一申请锁的话
就立刻考虑给它
让前面这个运行的程序
放弃这个锁
那就要看看说持有锁的线程
能否很快释放锁
那为了让这个线程等待
我们需要让线程
执行一个这个忙循环
也就是让它自旋
那这种技术就叫做自旋锁
那初步的话
java当中默认的这个自旋的次数
就是10次
当然你说为什么一定要自旋10次
为啥不是12次 为啥不是5次
为啥不是100次
那我们可以考虑
再改进这个问题的话
就采用自适应的这种自旋
自适应自旋的话
意味着锁自旋的时间不再固定
而是由前一次
在同一个锁上的自旋时间
及锁拥有者的状态来去决定
如果在同一个锁对象上
自旋等待刚刚成功获得锁
并且持有锁的线程
正在运行过程当中
那虚拟机就会认为
这次自旋也很有可能再次成功
进而允许自旋等待
相对更长的一段时间
所以这种就叫做自适应自旋
锁消除 什么是锁消除
我们的java虚拟机
java虚拟机即时编译器
在运行的时候
对一些代码上要求同步
但是它又能就是说检测到
不可能存在共享数据竞争
那这些锁的话
我们的java编译器
就可以把它消除掉
能达到这样的效果当然好了
也就是说我们写代码的时候
你是要求加锁的
但是编译器比较智能
能判断出来
这个加的这个锁是不必要的
那怎么判断呢
判断依据就是
如果在一段代码当中
堆上的所有数据
都不会逃逸出去
从而被其他线程访问到
那就可以把它们
当做栈上数据对待
认为他们是线程私有的
那这种同步锁就自然而然
不需要把它加上去
那这就是锁消除
锁粗化
那通常我们在写代码的过程当中
会尽量希望说
我们的同步代码块的作用范围
要尽量的小
使得共享数据的实际作用域
能够同步的进行
这样是使得同步操作的数量
尽可能的变小
但是如果我们都使用
很小的这种这个同步代码块的话
也容易产生另外一种不好的效果
也就是说如果
一系列的连续操作
都是对同一个对象
进行反复的加锁
甚至是在加锁操作
是出现在循环体当中
那即使没有线程争用
频繁的这种互斥同步
也会导致不必要的
这种性能的损失
那这个时候我们可以考虑
把我们写代码时候
这个同步的代码块的
这个范围扩大一下
比如说我过去Sequence
可能只包括了这个可能十行代码
可能我这时候我把Sequence
所包围的这些代码的数量
达到了20 甚至30行
就比原来代码行数更多
那这种的话就叫做锁粗化
偏向锁 那偏向锁的目的
是在消除数据无竞争
情况下的同步原语
进一步提高程序运行的性能
那偏向锁就是在无竞争的时候
把整个同步都消除掉
甚至连这个比较
并交换的操作都不做
也就是CAS操作
那这个偏向的含义是什么呢
它实际上指的是说
我们这个锁会偏向于
第一个获得它的线程
如果在接下来的执行过程当中
这个锁没有被其他线程获取
则持有偏向所得线程
永远不需要再进行这个同步
那这一节的内容
我们就介绍到这里
下面总结一下本章的学习内容
今天我们首先学习了
线程安全的概念
线程安全指的是
我们的访问对象
无论被多少个线程进行访问
都能够保证
我们这对象访问的正确性
那与之相关的这个概念
是线程兼容
那线程兼容是指
我们的对象本身
不是线程安全的
但是通过我们外部的同步控制
能够达到线程安全的目的
那这个就叫做线程兼容
而线程对立指的是
我们的访问对象
它本身不是线程安全
那我们外部即使加上了
同步的控制
也不能保证这个对象的
这个正确性
那这个就称之为线程对立
那在我们今天的学习过程当中
我们还学习的
实现线程安全的几种方式
首先是互斥同步
其次是非阻塞同步
第三是无同步方案
那这三种方式
都能够实现线程安全
最后我们还学习了锁优化
那锁优化的目标
就是在我们不得不给
我们的代码加锁的情况下
如何去提高锁的效率
进而达到提升
整个代码的效率的目标
以上就是本章的内容
谢谢大家
-1.0 导学
--Video
-1.1 线程的基本概念
--Video
-1.1 线程的基本概念--作业
-1.2 通过Thread类创建线程
--Video
-1.2 通过Thread类创建线程--作业
-1.3 线程的休眠
--Video
-1.3 线程的休眠--作业
-1.4 Thread类详解
--Video
-1.5 通过Runnable接口创建线程
--Video
-1.5 通过Runnable接口创建线程--作业
-1.6 线程内部的数据共享
--Video
-2.0 导学
--Video
-2.1 线程同步的思路
--Video
-2.2 线程同步的实现方式—Synchronization
--Video
-2.3 线程的等待与唤醒
--Video
-2.4 后台进程
--Video
-2.5 线程的生命周期与死锁
--Video
-2.6 线程的调度
--Video
-3.0 导学
--Video
-3.1 线程安全与线程兼容与对立
--Video
-3.2 线程的安全实现-互斥同步
--Video
-3.3 线程的安全实现-非阻塞同步
--Video
-3.4 线程的安全实现-无同步方案
--Video
-3.5 锁优化
--Video
-4.0 导学
--Video
-4.1 URL对象
--Video
-4.2 URLConnection对象
--Video
-4.3 Get请求与Post请求
--Video
-4.4 Socket通信原理
--Video
-4.5 Socket通信实现
--Video
-5.0 导学
--Video
-5.1 Socket 多客户端通信实现
--Video
-5.2 数据报通信
--Video
-5.3 使用数据报进行广播通信
--Video
-5.4 网络聊天程序
--Video
-6.0 导学
--Video
-6.1 Java虚拟机概念
--Video
-6.2 Java虚拟机内存划分
--Video
-6.3 Java虚拟机类加载机制
--Video
-6.4 判断对象是否存活算法及对象引用
--Video
-6.5 分代垃圾回收
--Video
-6.6 典型的垃圾收集算法
--Video
-6.7典型的垃圾收集器
--Video
-7.0 导学
--Video
-7.1 集合框架与ArrayList
--Video
-7.2 LinkedList
--Video
-7.3 HashMap与HashTable
--Video
-7.4 TreeMap与LinkedHashMap
--Video
-7.5 HashSet
--Video
-8.0 导学
--Video
-8.1 Java反射机制
--Video
-8.2 Java静态代理
--Video
-8.3 Java动态代理
--Video
-8.4 Java 反射扩展-jvm加载类原理
--Video
-8.5 Java进阶课程总结
--Video