-
ThreadLocal:ThreadLocal的作用主要是做数据隔离,填充的数据只属于当前线程,变量的数据对别的线程而言是相对隔离的,在多线程环境下,防止自己的变量被其它线程篡改。
Spring框架里面就是用的ThreadLocal来实现这种隔离,主要是在
TransactionSynchronizationManager
这个类里面简单原理:每个线程Thread都维护了自己的threadLocals变量,所以在每个线程创建ThreadLocal的时候,实际上数据是存在自己线程Thread的threadLocals变量里面的,别人没办法拿到,从而实现了隔离
-
ReentrantLock: 可重入锁
- void lock():加锁,如果锁已经被别人占用了,就无限等待。 大规模得在复杂场景中使用,是有可能因此死锁的。因此,使用这个方法得非常小心。
- boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException:尝试获取锁,等待timeout时间。同时,可以响应中断。 (可以有效预防发生死锁 )
- void unlock() :释放锁
- 重入锁使得同一个线程可以对同一把锁,在不释放的前提下,反复加锁,而不会导致线程卡死。因此,如果我们使用的是重入锁,你唯一需要保证的,就是unlock()的次数和lock()一样多
- 锁使用完后,千万不要忘记把它释放了
-
volatile
首先关联到的就是JMM(Java Memory Model)
线程对变量的所有的操作(读,取)都在工作内存中完成,从而导致了 可见性问题 ,及一个线程修改了主内存中的变量值后,其他线程还是使用的旧值,导致不一致问题,从而引出了validate。概述:
1、怎么发现数据是否失效呢?嗅探机制,会导致总线风暴问题
2、禁止指令重排序(通过内存屏障实现)
3、无法实现原子性(可以使用原子操作类避免如: AtomicInteger 等)
4、 volatile提供了可见性(MESI缓存一致性实现),任何一个线程对其的修改将立马对其他线程可见,volatile属性不会被线程缓存,始终从主 存中读取
-
synchronized
1、可重入性
synchronized锁对象的时候有个计数器(存在对象的 对象头 中),他会记录下线程获取锁的次数,在执行完对应的代码块之后,计数器就会-1,直到计数器清零,就释放锁了
2、不可中断性
不可中断就是指,一个线程获取锁之后,另外一个线程处于阻塞或者等待状态,前一个不释放,后一个也一直会阻塞或者等待,不可以被中断。
值得一提的是,Lock的tryLock方法是可以被中断的
3、同步代码块
monitorenter 代码块 monitorexit
4、同步方法
特殊标志位 ACC_SYNCHRONIZED
同步方法的时候,一旦执行到这个方法,就会先判断是否有标志位,然后,ACC_SYNCHRONIZED会去隐式调用刚才的两个指令:monitorenter和monitorexit
多线程的ThreadLocal、ReentrantLock、volatile、Synchronized
最新推荐文章于 2021-08-27 23:56:53 发布