volatile、threadLoocal

1.threadLocal、volatile、synchronized区别:
synchronized关键字是Java利用锁的机制自动实现的,一般有同步方法和同步代码块两种实现方式,synchronized代码块是通过monitorenter和monitorexit实现,synchronized方法是通过在方法常量池中的方法表结构中的ACC_SYNCHRONIZED 标志区分是否是一个同步方法,如果是则用Klass作为锁对象。
volatile是修饰变量的,在java内存模型中,所有变量都存储在主内存中,所有线程都可以访问,每个线程创建时,JVM都会为线程创建一个工作内存,线程对变量的操作是在工作内存中进行的,volatile修饰的变量发生变化时,所有调用该变量的线程都会获得最新相同的值,保证修饰的变量具有可见性,都但不能保证操作的原子性,还能禁止进行指令重排
threadLocal只是一个线程的局部变量,ThreadLocal会为每个使用该变量的线程提供独立的变量副本。每个线程内部都会维护一个threadLocalMap,map中的key为threadLocal,即每个线程中的threadLocal是相互隔离的,通过以空间换时间的方式,进行线程间数据的隔离。
2.volatile如何禁止重排序:
volatile禁止重排序的规则:
1.第一个操作是volatile读,无论第二个操作是什么,都禁止重排序
2.第二个操作是volatile写,无论第一个操作是什么,都禁止重排序
3.第一个操作是volatile写,第二个是volatile读,禁止重排序
volatile修饰的变量,在编译时,会在指令序列中插入内存屏障来禁止重排序。java内存模型采用保守策略插入内存屏障。
在volatile写操作之前插入storestore屏障(禁止上面普通写和自己重排序)
在volatile写操作之后插入storeload屏障(禁止下面volatile读和写)
在volatile读操作之后插入loadload屏障(禁止下面普通读和自己重排序)
在volatile读操作之后插入loadstore屏障(禁止下面普通写和自己重排序)
3.volatile如何实现内存可见性:
在Java内存模型中,所有变量都存储在主内存中,所有线程都可以访问,每个线程创建时,JVM都会为线程创建一个工作内存,线程对变量的操作是在工作内存中进行的。会先写到工作内存,再更新到主内存中 ,被volatile修饰的变量,会将更新的值直接刷新到主内存中。
4.DCL(double check lock)是什么原因造成单例失效:
在创建对象时,由于对象的创建不是 原子操作,他包括:
1.分配对象的内存空间
2.初始化对象
3.将对象实例指向分配的内存空间
2和3可能会被重排序,导致在多线程环境下,导致单例失效
5.ThreadLocal为什么会导致内存溢出:
每个线程会存放一份自己的ThreadLocalMap,获取这个map是通过线程唯一标识获取的 ,ThreadLocalMap中存放的是Entry,Entry内部类,继承了WeakReference<ThreadLocal<?>>,使用了弱引用,对应的是ThreadLocal,而map的生命周期是线程的生命周期,如果线程一直存活,但是ThreaLocal被设置为null之后,ThreadLocal被回收了,但是value还是存活在map中,属于强引用,不会导致GC回收
,等value越积越多,就会导致内存溢出,尤其像线程池这种长期存活的线程,所以使用完ThreadLocal需要remove掉
6.threadLocal的使用场景
最常用的threadLocal的应用于数据库连接、session管理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值