zoukankan      html  css  js  c++  java
  • synchronized + volatile + ThreadLocal

    线程的共享 synchronized  +  volatile + ThreadLocal 

    <1> synchronized 锁住的是对象,当用它来锁住一个类时,实际上也是锁的一个对象。 用了synchronized 就没必要用 volatile, 对于 synchronized 锁住的对象。

    <2>最轻量的同步机制 volatile:
    特性:只保证可见性。 如定义一个static变量,在主线程中改变了它,分线程不能感知到主线程修改了它。
    适用场景:大量读,少量写。

    <3>ThreadLocal: 为每一个线程提供变量的副本,实现线程的隔离,每个线程只访问自己的数据。 如:spring在实现事务的时候,TransactionManager, @Transactional.
    为什么spring在实现事务的时候要引入ThreadLocal? 答案:每个线程保存自己的连接, 可能调用多次dao, 避免每次调dao都要传递参数connection。
    那么是不是可以考虑把 连接 绑定到这个线程上面?? 这就是spring在实现事务的时候使用 ThreadLocal 的原因。 一般用到的方法有: set(T) get() remove()
    Thread 类中有一个成员变量, ThreadLocalMap threadLocals。 ThreadLocalMap 以 ThreadLocal<>为键,里面定义了一个 Entry[]数组。 因为一个线程拥有的副本可能有多个,初始大小为16.

    class ThreadLocalMap{ static class Entry{} private Entry[] entry; } 通过位运算取到自己的副本。当我们set到ThreadLocal时,实际上是赋值给我们自己的ThreadLocalMap。
    当有重复的时候,它会用nextHashCode()再计算。 ThreadLocal不保证变量同步

    强引用:Object obj = new Object();
    SoftRefence 要发生内存溢出了,强制回收;
    弱引用:只要发生gc,就一定会回收; Entry extends WeakRefence. 可以看出ThreadLocal是软引用。
    虚引用:最弱。

    引发的内存泄露分析:
    Stack Heap

    ThreadLocalRef ---- ThreadLocal -- [key, value]
    /
    CurrentThreadRef ---- CurrentThread -- Map

    当我们发生gc时,threadLocal被回收,value就无法被引用到了。即发生内存泄漏。 解决办法: threadLocal.remove();

    get/set方法中都有调清除,但是不保证一定清除。 但是remove一定清除。 没内存泄露是可能一直在调用 set/get 方法

    那它为什么要用弱引用? 如果用强引用,发生内存泄漏就是必然的。因为Map指向的必然。。。。

    ThreadLocal 线程不安全??? 因为它可以存共享变量,虽然是不同的引用,但是实例是一个。

  • 相关阅读:
    echart自定义浮窗 增加点击事件
    原生js学习 选择dom
    GOjs版本2.0去除水印
    js 作用域
    javaScript的原型模式
    JavaScript的基本包装类型说明
    原生js 函数 callee属性
    Vue学习-基本指令
    js函数
    Kubernetes(一):云计算发展历程
  • 原文地址:https://www.cnblogs.com/greys/p/10732669.html
Copyright © 2011-2022 走看看