threadlocal synchronized ReentrantLock volatile


锁定实例方法和静态方法的区别
锁定实例方法,锁在 this 对象上,不同实例的锁互不影响 
锁定静态方法,锁在 class 对象上,所有实例共享同一把锁

synchronized 块
1.可以把方法内不需要同步的代码移出同步代码块
2.指定锁的对象,解决多个 synchronized 方法之间不需要共享同一把锁的问题

----------------------------------------
Synchronized 偏向锁 轻量级锁 重量级锁
Jdk1.6 对 Synchronized 锁做了优化
---------------------
无锁状态 没有线程竞争锁的时候
---------------------
第一个线程竞争锁的时候,无锁升级为偏向锁
---------------------
偏向锁状态 在锁对象的对象头里记录当前获取该锁的线程 ID,该线程再次获取该锁就能直接获取到了
---------------------
第二个线程竞争锁的时候,偏向锁升级为轻量级锁
---------------------
轻量级锁状态 底层是自旋 CAS,不会阻塞线程
---------------------
自旋太多次都没有获取到锁,轻量级锁升级为重量级锁
---------------------
重量级锁状态 
---------------------
重量级锁通过监视器 monitor 实现互斥锁,底层调用了操作系统的功能,开销较大
每一个锁对象都对应一个 monitor 对象,HotSpot 虚拟机是由 ObjectMonitor 实现的
如果使用 synchronized 给 obj1 对象上锁,obj1 的对象头会指向一个 monitor 对象

刚开始 Monitor 中 Owner 为 null,第一个竞争锁的线程判断出 Owner 为 null, 就持有锁同时 Owner 指向该线程

锁池 ObjectMonitor.EntryList
Owner 不为 null 的时候,其他线程竞争锁就放入 monitor 的 EntryList 阻塞队列中,处于阻塞状态 Blocked
当前面的线程释放锁,将 owner 置为 null,并唤醒 EntryList 中阻塞的线程来竞争锁
等待池 ObjectMonitor.WaitSet
获得锁的线程调用 wait() 后,线程会进入等待池,等待池的线程在调用 notify() 或 notifyAll() 之前不会竞争锁,notify() 随机从等待池选出一个线程放到锁池,而 notifyAll() 将等待池的所有线程放到锁池当中
-----------------------------
Synchronized 和 ReentrantLock
1.Synchronized 是一个关键字,ReentrantLock 是一个类
2.Synchronized 自动加锁释放锁,ReentrantLock 需要手动加锁释放锁
3.Synchronized 是 JVM 层面的锁,ReentrantLock 是 API 层面的锁
4.Synchronized 是非公平的锁,ReentrantLock 可以选择公平锁或非公平锁
5.Synchronized 锁信息保存在对象头中,ReentrantLock 通过代码中 int 类型的 state 标示锁的状态
6.Synchronized 底层有一个锁升级的过程
-----------------------------
threadLocal 底层原理
底层通过 threadLocalMap 实现,每个 Thread 对象里都有一个 threadLocalMap,用来存储本线程中所有 threadLocal 对象及其对应的值,当用户调用 ThreadLocal.get()/set() 时,首先根据当前线程对象获取 threadLocalMap 对象,然后通过 threadLocalMap 来存取数据

在线程池中使用 threadLocal 会造成内存泄露,因为线程池中的线程不会回收,而线程对象强引用 threadLocalMap,
threadLocalMap 强引用 Entry 对象,Entry 对象用完了又没有及时调用 remove(), 又回收不了
所以应该用完 threadLocal 对象后,及时调用 remove() 

使用场景
1.可以实现线程内跨多个方法传递数据
2.线程间数据隔离, 每个线程都访问数据的本地副本
Spring 申明式事务通过 threadLocal 存取 jdbc connection 对象来支撑事务的传播和隔离
zuul 里的 RequestContext 通过 threadlocal 来保存每个请求的相关信息

-----------------------  
Volatile 不能大量使用
由于 Volatile 的 MESI 缓存一致性协议,需要不断的从主内存嗅探和cas不断循环,无效交互会导致总线带宽达到峰值
----------------------------------------
volatile 与 synchronized 的区别
volatile 用于修饰变量,synchronized 用于修饰方法或代码块
synchronized 是一种互斥的机制,volatile 属性无锁读写
----------------------------------------
volatile 保证属性的可见性,修改 volatile 属性时,会直接将 CPU 高速缓存中的数据写回主内存,读也是直接从主内存读,适合一个线程写多个线程读的场景

volatile 底层是通过操作系统的内存屏障来实现的,内存屏障会禁止指令重排,这样就保证了有序性,以前用于解决单例双重检查对象初始化代码执行乱序的问题
----------------------------------------
ThreadLocal 与 synchronized
ThreadLocal 并发性能比 synchronized 要好一些
synchronized -- 用于多个线程互斥的操作资源
ThreadLocal -- 用于让每个线程都操作本地副本
ThreadLocal 可用于线程内跨越多个函数调用的数据读取,例如,spring 事务把 connection 放到 ThreadLocal 中,方便事务传播,统一提交回滚
----------------------------------------


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叫我三师弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值