volatile 与 ThreadMap 区别及用法

本文讨论了volatile关键字在多线程中的可见性和有序性,以及与ThreadLocal的区别。ThreadLocal提供线程局部变量,保证数据隔离。通过示例代码,分析了并发问题并提出了使用AtomicInteger或synchronized解决非原子性问题的方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

volatile 与 ThreadMap 区别及用法

volatile 关键字

  1. 作用

    • volatile 关键字用于声明一个变量,它确保了该变量在多线程环境下的可见性和有序性。
      • 可见性当一个线程修改了volatile变量的值时,其他线程能够立即看到这个修改的结果,无需通过显式同步(如synchronized)来实现。这是因为volatile变量的写操作会强制刷新到主内存,并且读操作也会始终从主内存中读取最新的值。
      • 有序性:编译器和CPU的指令重排序优化不能违反volatile变量的操作顺序,这有助于保持多线程环境下的程序执行顺序的一致性。
  2. 不保证原子性

    ​ 单独的volatile变量读/写操作是原子的,但复合操作(例如递增或递减)不是原子性的。即使变量被volatile修饰,也不能防止多个线程同时对其操作造成的数据不一致性问题。

  3. 适用场景

    • 常用于表示状态标志、中间状态标志、或者其他只需要保证可见性和有序性,而不涉及复合操作的状态变量。

ThreadLocal 类

  1. 作用
    • ThreadLocal 类提供了线程局部变量。每个线程都有自己的ThreadLocal实例副本,各线程间互不影响。
      • 数据隔离:ThreadLocal变量在每个线程内部都有自己独立的副本,因此线程间的数据是完全隔离的,不会发生数据竞争。
      • 避免同步开销:由于每个线程使用各自的副本,因此在多线程环境下,使用ThreadLocal可以减少甚至消除因共享数据带来的同步开销。
  2. 工作原理
    • ThreadLocal内部维护了一个ThreadLocalMap,该映射表的键是ThreadLocal对象本身,值是每个线程绑定的变量副本。因此,每当线程访问ThreadLocal变量时,都会得到与当前线程绑定的专属值。
  3. 适用场景
    • 适用于那些需要在线程内部维持独立状态,且这个状态与其他线程无关的场景,例如每个线程的事务ID、用户登录信息、数据库连接、线程特定的日志记录器等。

示例代码

package com.gbl.demo.util;


import com.google.common.collect.Maps;

import java.util.Map;

/**
 * @Author: dx
 * @Date: 2024/3/14 17:51
 * @Description: 线程工具示例类
 */
public class ThreadUtilDemo {
   

    // volatile 线程计步器
    volatile static int threadStep = 0;
    // 线程1
    public static Thread fistThread;
    // 线程2
    public static Thread secondThread;
    // ThreadLocal 对象
    public static ThreadLocal<Map<String, Integer>> threadLocalMap = new ThreadLocal<>();

    static {
   
        // 线程一实例化
        fistThread = new Thread(() ->
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值