当前课程知识点:JAVA程序设计进阶 > 第三章 线程(下) > 3.4 线程的安全实现-无同步方案 > Video
这一节我们来介绍一下
线程安全的第三种实现方式
无同步方案
那无同步方案的话
首先我们可以采用
可重入代码的方式
也叫做纯代码
相对于线程安全的实行来说
重入代码也可以保证线程安全
那我们可以在
代码执行过程当中去中断它
转而去执行另外一段代码
当这个我们控制权返回以后
原来的程序也不会出现任何错误
那实现无同步方案的话
另外一种方式就叫做
线程本地存储
如果一段代码中所需要的数据
必须与其他代码共享
那我们就看看这些
共享数据的代码是否能保证
在同一个线程当中去执行
如果能保证的话
就可以把共享数据的可见范围
限定在同一个线程当中
这样就不需要这个同步
也能够保证线程之间
不出现数据争用的这个问题
那我们下面给大家介绍一个
这个线程本地存储的例子
Threadlocal
那Threadlocal的话
本身是我们java当中的一个类
它是存在于java.lang
这个默认这个包当中
那我们来看看我们这个程序
public class SequenceNumber
我们看一下它的这个
定义的第一个成员变量
private static ThreadLocal
Integer seqNum
seqNum这个是它的一个成员变量
那我们看它等号后边
怎么进行初始化
等于new Threadlocal
然后Integer
然后我们再看一下
后面竟然跟着大括号
其实它是通过匿名类
来去覆盖我们Threadlocal的
initialValue这个方法
来去指定它的初始值
那怎么指定呢
我们看看那个
public Interer initlalValue
这个方法
我们直接返回到0 return 0
那我们接着再往下看
publicint getNextNum
那这个方法的目的
是要获取下一个序列值
那到底怎么获得下一个序列值呢
我们往下看seqNum.set
然后括号seqNum.get再加1
也就是说我通过
刚才上面刚刚定义完的
那个成员变量seqNum
调用它的get方法
就可以获得它的值
然后我再加1
然后再把它设回去
就是通过set这个方法
重新设成我们seqNum的新的值
最后的话怎么返回呢
return seqNum.get
就获得它新的这个序列值
然后并把它返回回去
我们再往下看主方法
public static vold main
string args
然后SequenceNumber sn
等于new SequenceNumber
大家还记得这个
SequenceNumber这个类在哪吗
SequenceNumber这个类
其实就是我们这个
代码中的第一行
也就是我们正在定义的这个类
public class SequenceNumber
那我们这个主方法当中
去声明了这么一个类的对象sn
然后并进行实例化
我们接着往下看
TestClient t1
等于new TestClient sn
TestClient是一个什么对象呢
其实大家看底下这个四五行后
有一个定义的一个内部类
叫private static class
TestClient extends Thread
它原来是一个线程类
我们先不管它这具体内容
我们又回到我们这个
这一页的第二行
TestClient t1
等于new TestClient sn
TestClient t2
等于new TestClient sn
TestClient t3
等于new TestClient sn
其实我们是在创建了三个线程
名字分别叫t1 t2 t3
而这个线程的类型
就是TestClient
然后那调用它的构造方法的时候
所以给的这个参数
就是那个sn序列 序列号
那其实每给一个sn的话
它其实它都会有
数值是有变化的
那再往下看我们是t1.start
t2.start t3.start
这三个线程启动了
那我们看完这三个线程
它的每个线程
具体都在干些什么事情
我们看下面的代码
private static class
TestClient extends Thread
然后private SequenceNumber sn
它也有个成员变量
它的这个叫sn
然后类型是SequenceNumber
我们再看它的构造方法
public TestClient
SequenceNumber sn
然后this.sn等于sn
其实是把这个通过构造方法
传入一个对象sn
然后并把它复制
复给这个类的成员变量sn
我们再往下看一下run方法
public void run
run方法的话
它的主要目的就是这个循环三遍
然后每一次都要打印出
我的线程的名字
通过Thread类的getName这个方法
得到线程的名字
再加上我们这个sn
这个序列号的值
也就是sn减getNextNum它的值
那总结下来就是说
我们这三个线程
每个线程在执行过程当中
它主要功能是打印名字
并打印出它的这个
序列号的这个值
而且大家应该也看到
这个序列号的话
应该它也是会这个逐步往下加的
那这是我们的一个运行的结果
大家看到分别是
Thread2打印它序列号1
然后接着Thread0
打印它的这个序列号1
这个Thread1
打印它的序列号1
紧接着后面这三个线
又各自打印出它的序列号2和3
那在这个例子中
我们通过这个匿名内部类的方式
定义了ThreadLocal的子类
提供了初始的变量值
就在我们第一个这个注释的地方
那TestClient线程
它产生了一组序列号
那我们能够生成三个这个
TestClient这个线程对象
它们实际上共享的是同一个
SequenceNumber的这个实例
其实大家也看得出来
就是我们这三个线程
实际上它是共享了
这个SequenceNumber的实例
那我们通过我们用
ThreadLocal的这个方式
也能够保证这三个线程
来访问同一数据的时候
没有产生错误的
这么一种这个情况
这也是我们为什么说
我们要可以通过
这个ThreadLocal
就来去达到我们这个同步
就是说安全的这个目的
也不一定非得说
我要加个Sequence
因为如果你一旦加了
Sequence的话
性能可能是会受到影响
那如果我们能通过
类似ThreadLocal这样这种本地
就线程的本地存储的方式
来达到我们这个对于数据
访问安全的控制化
那我们就能提高
我们这个程序代码的性能
这些就是我们本节的内容
-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