ThreadLocal、Atomic、synchronized、Volatile

一、前提

首先我们要知道这四个关键词都是干什么,都是用来解决多线程处理数据造成不同的
什么是原子操作:
原子操作就是不被多线程影响的操作,是不能中断的操作,例如对域进行赋值和返回都属于原子操作,但是在 java 中 i++ 和 i+=2 这种操作不属于原子操作(c++是属于的),所以我们就引入了我们的 Aotmic 类。


二、Atomic

基于 Lock-free 算法,限制多线程对同一个资源进行处理的,它是对于原子的操作类,
它使用 Lock-free 算法替代锁,这样的话开销小,速度快, 对于原子操作类是采用原子操作指令实现的,从而可以保证操作的原子性。什么是原子性?比如一个操作i++;实际上这是三个原子操作,先把i的值读取、然后修改(+1)、最后写入给i。所以使用Atomic原子类操作数,比如:i++;那么它会在这步操作都完成情况下才允许其它线程再对它进行操作,而这个实现则是通过Lock-Free+原子操作指令来确定的
可以看到Lock-free通过三步来进行的,1、循环 2、CAS 3、回退
比如在多个线程操作一个count变量的情况下,则可以把count定义为AtomicInteger,如下:
在每个线程中通过increment()来对count进行计数增加的操作,或者其它一些操作。这样每个线程访问到的将是安全、完整的count。
可以看到我们在申请 count 变量的时候,首先是 通过AtomicInteger 进行修饰的

内部实现:

采用Lock-Free算法替代锁+原子操作指令实现并发情况下资源的安全、完整、一致性
总结:主要是使用 compareAndSet 这个方法去判断操作是否可以进行
compareAndSet(expectedValue, newValue) : 如果当前值(current value)等于期待的值(expectedValue), 则原子地更新指定值为新值(newValue), 如果更新成功,返回true, 否则返回false

缺点:如果多个对象需要进行线程访问保护,那么就不建议使用 Atomic 了
特点:性能非常好


三、Volatile

这个是轻量级的 synchronized ,他最大的特点是可以在多并发的时候保障变量的可见性,什么是可见性,就是在我们线程的内存中修改了变量的值,它会立刻同步到主存中,保证所有变量看到这个值是一致的,而且它的开销比 synchronize 小。
我们的单利模式中常用的就是
Volatile+DCL(双检查锁定)
Volatile 的操作也是由局限性的,因为他对数据的操作不具有原子性,比如数据的操作依赖它自己,如果使用 Vloatile 就会有问题,例如 count++
这样就会有问题


四、synchronized

这个类叫做同步锁,是Lock 的一个简化版本,性能肯定没有 Lock 好,不过他的操作实在是太方便了,所以被广泛使用了
它的原理就是当
所有线程对这块区域的代码访问必须先持有锁才能进入,否则则拦截在外面等待正在持有锁的线程处理完毕再获取锁进入,正因为它基于这种阻塞的策略,所以它的性能不太好,但是由于操作上的优势,只需要简单的声明一下即可,而且被它声明的代码块也是具有操作的原子性。



五、ThreadLocal

首先 ThreadLocal 不是用来解决并发问题的,ThreadLocal.set 的对象是属于线程自己的对象,其他线程是访问不了的。每个线程访问的对象都是不同的
每个线程都有一个 map 叫做 ThreadLocalMap,每次调用 ThreadLocal.set 的时候都会像本线程的 map 中添加一个 key-value 对,key 为 ThreadLocal ,value 是我们想要添加的值,当我们调用 get 方法的时候原理就是一样的了,所以说每个线程的对象都是自己独有的。
另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。 通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。
应用场景:
ThreadLocal的应用场合,我觉得最适合的是按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。 

实现原理:

ThreadLocal 里面有一个内部类叫做 ThreadLocalMap 这个类的作用就是用来存储ThreadLocal 和 value 的对应值的,每个 Thread 中都有一个 ThreadLocalMap 实例,在这个实例中存储着每个 ThreadLocal 对应的 value,在ThreadLocal的set函数中,可以看到,其中的map.set(this, value);把当前的threadlocal传入到map中作为键,也就是说,在不同的线程的threadlocals变量中,都会有一个以你所声明的那个线程局部变量threadlocal作为键的key-value。假设说声明了N个这样的线程局部变量变量,那么在线程的ThreadLocalMap中就会有n个分别以你的线程局部变量作为key的键值对。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值