多线程之并发工具

ThreadLocal

除了将变量定义为immutable以外,ThreadLocal提供了新的线程安全思路。
ThreadLocal实现线程安全是将变量独立的保存到每个线程中,这样就不存在竞争问题,也就用不到互斥锁了;同时每个线程中都有一个变量的独立副本(该副本对其他线程不可见),也不用考虑线程安全问题。
实现上,ThreadLocal类中没有存储结构,ThreadLocal依赖于当前线程中的threadLocalMap存储

    public void set(T value) {
    	// 获取当前线程
        Thread t = Thread.currentThread();
        // 获取当前线程的ThreadLocalMap
        ThreadLocalMap map = getMap(t);
        if (map != null) {
	        //ThreadLocalMap已经被初始化,已当前threadLocal对象为key,添加value
            map.set(this, value);
        } else {
        	//如果未初始化,则新建表
            createMap(t, value);
        }
    }

通俗一点总结,Thread中存在一张ThreadLocal变量表,每新建一个ThreadLocal对象,就会向变量表中添加一个变量,每个线程的变量表独立不共享,从而实现线程安全。

内存泄漏

首先我们看一下ThreadLocalMap的内部类Entry

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

也就是说,Map中作为key的ThreadLocal是个弱引用,下次GC就没了,就变成了(null,value)
在这里插入图片描述
也就是图中的虚线部分,这时候对于ThreadLocal来说,这个value就是不可见的,应当回收
但在线程池中,线程可以长时间存在,每个线程持有threadLocalMap的强引用,进而导致无效键值对(null,value)被判断为可达,也就不会被释放,从而产生内存泄漏。
因此在时候ThreadLocal时,要及时remove已经set的值

如果key设计为强引用是否可以避免内存泄漏的发生呢?
事实上设计成弱引用是有道理的。如果key和ThreadLocal之间是强引用,根据可达性分析,除非当前线程结束,否则TheadLocal是永远不会被收回的,这又造成了内存泄漏

原子类

原子类的实现依赖于乐观锁CAS

CAS

所谓的乐观锁,实际就是不上锁,不断循环重试条件,直到达到条件。
CAS全程compare and swap,可以用三元组(V,O,N)描述。其中V表示操作变量的地址,O是预期的旧址(将要被替换的值),N是预期的新值(将要替换的值)。此外CAS还是一个原子操作,其由一条底层指令CMPXCHG 实现。

但是CAS仍存在一定的问题:ABA
CAS比较旧值是否发生变化 作为 是否被修改过的依据。可如果修改过程为A->B->A,旧值没有变化但是的确被修改过,这样的修改是CAS不能分辨的,也就是ABA问题。
对于这个问题的解决 可以添加版本号/时间戳来避免

以下以AtomicInteger为例进行介绍

常用方法

// 替换新值,返回旧值
public final int getAndSet(int newValue) {
    return U.getAndSetInt(this, VALUE, newValue);
}
//自增,返回旧值
public final int getAndIncrement() {
    return U.getAndAddInt(this, VALUE, 1);
}
//自增,返回新值
public final int incrementAndGet() {
    return U.getAndAddInt(this, VALUE, 1) + 1;
}
// 相加,返回旧值
public final int addAndGet(int delta) {
    return U.getAndAddInt(this, VALUE, delta) + delta;
}

参考链接:

  1. 关于ThreadLocal的使用可能造成的内存泄露以及避免方案以及为什么使用弱引用
  2. Java中atomic包中的原子操作类总结
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CountDownLatch是Java并发编程中的一种同步工具类。它的作用是允许一个或多个线程等待其他线程完成操作。CountDownLatch的构造函数接收一个计数值,当计数值变为0时,等待的线程就会被唤醒。使用CountDownLatch可以实现多线程并发编程中的线程协作。 与使用join方法等待多个线程执行完毕不同,CountDownLatch相对灵活。可以通过调用countDown方法来减少计数,唤醒被阻塞的线程。这使得多个线程可以同时进行,并在一定条件下等待其他线程完成后再继续执行。 CountDownLatch一般称为闭锁或计数器,它是Java并发编程中的一种多线程同步工具。它属于AQS(AbstractQueuedSynchronizer)体系的一员,可以实现线程之间的协作和同步操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Java多线程并发工具类](https://download.csdn.net/download/weixin_38713057/13756829)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [java多线程并发之CountDownLatch](https://blog.csdn.net/weixin_42419762/article/details/116220340)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [多线程编程之 CountDownLatch](https://blog.csdn.net/jiangxiayouyu/article/details/118107977)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值