线程安全笔记


线程安全核心是对共享以及可变的状态的访问

- 共享意味着可以多个线程访问
- 可变意味着变量值在其生命周期内可以变化

所见即所得即为正确性

线程安全不仅仅在写入时使用同步,获取也要使用同步

活跃性问题

含义为某个正确性的结果最终会发生
产生的问题有 活锁 死锁 

竞态条件

由于不恰当的执行时序而出现的不正确的结果 叫做竞态条件(当某个结果的正确结果依赖于多线程的交替执行)

先检查后执行(Check then act)

++i 和i++ 可以通过automic 变成线程安全

延迟初始化中的竞态条件(属于先检查后执行常见的一种)

例如懒加载

最低安全性


当线程在没有同步状态下读取变量值时,可能会获取到一个旧值,这个叫做最低安全性。
但是非volatile修饰的64位数值变量double和long 类型数据不能满足最低安全性,他会被jvm分解为两个32位来计算。

线程封闭

栈封闭

利用局部变量来访问对象:在方法中克隆传递的参数。这样这个参数只存活于栈中

ThreadLocal

通常用于防止对可变的单例变量或者全局变量进行共享

内置锁


synchronized block  包含两部分 一个作为锁的对象引用,一个作为由这个锁保护的代码块

//lock为被锁的对象
synchronized(lock){
//花括号里面是被保护的代码块
}

volatile

volatile 不会放入寄存器
满足以下条件才可用volatile

- 对变量的写入操作不依赖当前变量的值(对状态标志的修改,因为volatile不能保证原子性),或者只有单个线程修改变量值
- 该变量不会与其他变量纳入不变性条件中
- 在访问变量时不需要加锁(volatile访问时不会线程阻塞)

不可变对象

1.对象创建以后状态就不可更改
2.对象的所有域是final类型
3.对象是正确创建的(对象创建期间,this引用没有在构造函数中逸出)


不可变对象是线程安全的

安全发布的常用模式

1.在静态初始化函数中初始化一个对象引用
2.volatile修饰(安全性比较低)或者AutomicReference对象中
3.将对象保存到某个正确构造对象的final域中
4.由锁保护的同步方法中

设计线程安全类的要素


1.找出构成对象状态的所有变量
2.找出约束状态变量的不变性条件
3建立对象状态的并发访问管理策略

双端队列Deque


实现了再对头和队尾的高效插入和删除
工作密取使用这种模式(工作队列从头部获取,空闲队列从尾部获取)

闭锁

countDownLatch ,FutureTask
延迟线程的进度直到一个终止状态,一旦进入终止状态就不能被重新开启

响应中断


如果线程中有阻塞的代码,不能在catch exception 中调用interrupt 不然可能会引起无限循环,因为大部分阻塞方法会在入口判断线程状态
解决方案 在finally中重新中断

线程池


如果请求速率大于线程池处理速率,线程池将会用一个runnable和一个队列保存待处理的任务


队列分为 无界 有界和同步移交

synchronous 并不是一个队列,而是一个线程之间移交的机制,将一个任务放入同步移交中时,必须有一个工作线程在等待,如果没有,并且当前活跃线程小于设置的最大线程数,则开启一个新线程
newFix 和 sigle 使用一个无界的队列
cache使用synchronousQueue

无界队列会导致资源的耗尽

实例封闭


将不安全的类作为变量封装到 宁外一个类中,并封装线程安全的方法来访问这个变量

使用私有的锁对象

相比于synchorized(this)而言会把锁封装起来 使得客户端获取不到锁,但是客户端可以通过公有方法访问锁

在现有的线程安全类中添加功能

在原始类中添加一个方法

继承原始类 实现新方法(扩展)

通过一个辅助类加锁(注意锁的对象不是辅助类,而是线程安全的对象)

##各类显式锁

ReentrantReadWriteLock


读锁共享,写锁独占
在队列中第一个写入请求前的读取请求共用一个锁

建立高效可伸缩的结果缓存


 1.HashMap 非线程安全,如果在方法上加同步关键字,则同一时刻只有一个线程可以通过
 2.ConCurrentHashMap ,分段锁,可伸缩性强,但是碰到并发情况下,可能会出现重复计算问题
 3.利用ConCurrentHashMap+Future ,利用ConCurrentHashMap的key 放关键字,value放Future,如果get(key)不为空则future.get()等待获取结果,这样无需计算,如果future为空则新建一个futuretask放入Map中,再调用future.get 阻塞
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值