当前课程知识点:JAVA程序设计进阶 > 第三章 线程(下) > 3.2 线程的安全实现-互斥同步 > Video
刚才我们已经介绍了
线程安全的概念
那这一节我们将介绍
如何去实现线程安全
那实现线程安全的话有多种方式
那我们今天将介绍
互斥同步 非阻塞同步
无同步方案等三种方式
那第一种实现方式就是互示同步
那我们对同步的话
它在互斥实现的过程当中
可以采用临界区 或者互斥量
或者信号量等方式来进行实现
那这些实现方式
如果大家学过
操作系统课程的话
都可以接触到这些内容
那在我们java当中的话
要实现互斥的话
所采取的方式就是
使用synchronized关键字
那大家在前面学习的过程中
已经多次看到了
这样的这个关键字
那如果你在写
java源代码过程当中
加入synchronized关键字
那我们的java编译器
在编译的时候
就会在我们的同步代码块的前面
加入一个字节码
叫monitorenter
那在同步代码块的最后
加入monitorexit这个字节码
实际上就是
把我们需要同步的这些代码块
分别对它的入口和出口
做了一个标识
这样当我们的这些同步代码块
在执行的时候
就能够被这个java的
运行环境所识别
那这个synchronized同步块
对自己它是可重入的
不会把自己给锁死
那当这些同步块
在进入到线程的执行完成之前
它就会阻塞其他线程的进入
以保证我们这种数据的安全性
实现我们的互斥与同步
那实现互斥同步的话
另外一种方式可以用重入锁
就叫Reentrantlock
那这么这个类的话
是来自于我们java当中的
另外一个包
叫java.util.concurrent这个包
那我们用这个重入锁的话
它相比我们之前用synchronized
这个关键字来说
它的优点是可以实现等待可中断
以及实现公平锁
甚至实现锁去绑定多个条件
这是采用Reentrantlock
这个类的一个好处
那synchronized它表现为
就是原生语法层面的互斥锁
而Reentrantlock
它表现为API层面的互斥锁
下面我们通过这么一个例子
来去告诉大家
这个Reentrantlock
到底是怎么使用的
我们看一下代码第一行
import java.util.concurrent.
locks.reentrantlock这个类
我们看一下
我们定义的类的名字
public class Bufferinterruptibly
在这个类当中有一个成员变量
叫private reentrantkock lock
等于new Reentrantlock
紧接着我们定义
我们这个类的一个方法
叫public vaid write
run方法里面第一行
lock.lock方法
其实这行代码意思就是
我要对我的那个重入锁
Reentrantlock
这个lock对象
我要调用它的加锁功能
就是lock功能
这个功能其实的话
给大家打一个通俗的比方
就比如说你在进入这个
更衣室的时候
你就会把那个锁给锁上
那这时候再进行相应的操作
我们看那个我们下面
进行哪个操作呢
try long startTime
等于System.currentTimeMillis
就是说我要得到当前的这个时间
紧接着我们打印
System.out.println
往这个我们的这个一个缓冲区
去写数据
紧接着我们做了一个无限循环
for这个无限循环
是用来模拟一下这个处理时间
然后我们会在这个循环当中
去判断说如果当前的时间
减掉刚才我们这个
起始时间System
大于某一个预值的时候
那我们这个循环就结束
那我们大于哪个预值呢
就是大于我们Integer
这个类的它的最大值
也就是我们这个整型数
就是这个32位整型数的
它的最大值的时候
我们循环就结束了
结束完以后我们说就打印出来
终于这个往这个缓冲区
写内容的操作写完了
最后finally lock.unlock
这我用红色给它标出来
这时候就把锁打开了
那其实大家看这个例子
实际上是非常通俗易懂
也就是说当你想要执行
你那些代码的时候
你一开头先把锁给锁上
然后你这个代码执行完了以后
你再把锁这个打开
这个就像我刚才给大家举的例子
比如说你去买一幅
你要去一个那个更衣室
去试着衣服
进了这更衣室你把门锁上
然后你把衣服试完挑好以后
你再把这锁打开你就出来
然后这时候这更衣室
就可以继续被别人使用了
所以这个体现了
我们这个程序当中
就是两个操作
一个是lock锁的操作
然后另外一个就是unlock
开锁的这个操作
那再往下的代码
就是它的另外一个方法
叫public void read
读的这个方法 读的方法
那刚才上一个方法是写的方法
那读的方法里面
我们看它的方法体第一行
lock.locklnterruptlbly
也就是说它也是加锁
只不是说我在加锁的时候
这种锁的话还可以响应中断
紧接着我们就
System.out.println
我就打印出来
从这个缓冲区里读数据
finally最后我们lock.unlock
当我们读完了以后
我们就是把它锁打开
所以在这个读的方法里面
我们也是访问了lock这个对象
然后调用了它的这个加锁的方法
叫locklnterruptlbly
也调用它的开锁方法
lock.unlock
那通过这个例子也是想告诉大家
也就是说我们通过重入锁
就是reentrantlock
这个类的对象
我们一样也可以实现
代码之间的这种互斥同步
当然这个两种方法相比
也就是说我们使用重入锁
reentrantlock
和使用同步的关键词
synchronized
对于我们的这个程序的性能方面
会有什么影响呢
这是我们得到的两张
这个性能的这个比较图
每一张图它的这个横坐标
是我们程序运行时候的
这个线程的数量
纵坐标是它的这个
程序的这个吞吐量
那从外边这张图当中
我们可以看到
它是在一个cpu的情况下
运行的性能对比
我们的蓝色的话
是采用了synchronized
这个关键词来进行
修饰的这些程序
这个粉红色的这个线条
是采用这个Reentrantlock
这种方法来进行这个实现的代码
我们可以从性能上来看得出来
用Reentrantlock
这个方法的话
它的这个吞吐率的话
一直还是维持在
比较高的一个状态
对于synchronized的话
它的吞吐率这个下降的比较快
而且也一直维持在
比较低的一个状态
那我们再看一下右边这张图
右边这张图 左边这张图的
不同之处是在于
是这个我们运行的这个电脑
是有四个CPU
那在有四个CPU的情况下
大家应该可以看到
我们的Reentrantlock
这条粉红色的这个线条的话
看到的这个结果
它的这个性能还比较平稳
一直在处于比较高位的这个状态
而用synchronized
这个来修饰的这个程序的话
它这个性能下降也是比较快的
所以从这两张图
大家也可以看到说
当你要实现你的互斥同步的时候
你有多种选择
但是如果你能选择一种
让你的程序性能
更好的一种代码实现方式
将帮助你的程序
取得更好的效果
那这一节内容
我们就介绍到这里
-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