并发编程
首先感谢https://blog.csdn.net/iter_zc/article/details/39546405这个系列的作者。之前接触过高并发,但是都是在断断续续的接触和学习,没有一个结构化的学习。我的博文就是在看了他的讲解之后自己理解的。如果我写的不够好,大家可以去看一下大神写的,希望大家都可以提升自己的技术。
1. 并发编程的场景
java里面涉及到并发问题大多是多线程的问题,如果数据是无状态的(不会发生变化的)或者说线程封闭的,那么就不需要考虑多线程下的安全问题。如果数据必须是多个线程共享的,那么就必须要要考虑必要的解决方式。通常我们在项目里面遇见的多线程问题不是特别多,这是因为大多的数据可以满足前面两点,这也是正确的思路。我认为我们在项目里面应该尽量把变量满足无状态和线程封闭的要求,在保证效率的情况下,尽量避免线程安全问题。
2.如何避免并发问题
1.数据无状态
主要是一些只读不写的数据
2.线程封闭
线程封闭指的是数据是每个线程单独持有的,而不是共享。比如我们写web工程,其实理论上来说肯定是有线程安全的问题。但是tomcat会为每个请求创建一个线程直到请求结束。所以我们写的内部逻辑都是线程封闭的。但是在逻辑内部,如果还是存在多线程那么就可以考虑是否可以线程封闭。
#解决方式 ThreadLocal类
源码解读:ThreadLocal类最主要的三个方法就是set get remove
1.set()
public void set(T value) {
<br>
//调用JNI 获取当前线程<br/>
Thread t = Thread.currentThread();<br>
//下面介绍
ThreadLocalMap map = getMap(t);<br>
if (map != null)<br>
map.set(this, value);<br>
else
createMap(t, value);
}
//这个值是当前线程持有的一个变量
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
可以看出来ThreadLocalMap是当前线程持有的一个变量 继续点进去
ThreadLocal.ThreadLocalMap threadLocals = null;<br/>
//这个类是ThreadLocal类的内部类
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
上面的代码可以看出这个ThreadLocalMap这个类维护了一个Entry的内部类,Entry这个类继承了 WeakReference<> 这个类,WeakReference在java里面就是代表弱引用,每次JVM在进行GC的时候都会清除这个ThreadLocal<?>类的对象(为什么使用这种引用的原因后面讲)。这个类维护了一个key value类型的映射,key就是ThreadLocal对象。value就是实际的值。而ThreadLocalMap这个类内部有一个Entry数组来保存多个Entry对象。
接下来看map.set方法 在当前已经存在threadLocal的情况下
private void set(ThreadLocal<?> key, Object value) {