您好,登录后才能下订单哦!
密码登录
            
            
            
            
        登录注册
            
            
            
        点击 登录注册 即表示同意《亿速云用户服务条款》
        # Java多线程之间如何共享数据
## 目录
1. [多线程数据共享概述](#一多线程数据共享概述)
2. [共享数据的问题与挑战](#二共享数据的问题与挑战)
3. [基本共享方式](#三基本共享方式)
4. [线程安全的数据结构](#四线程安全的数据结构)
5. [锁机制详解](#五锁机制详解)
6. [原子变量类](#六原子变量类)
7. [volatile关键字](#七volatile关键字)
8. [ThreadLocal实现线程隔离](#八threadlocal实现线程隔离)
9. [并发容器使用场景](#九并发容器使用场景)
10. [最佳实践与性能考量](#十最佳实践与性能考量)
11. [总结](#十一总结)
---
## 一、多线程数据共享概述
### 1.1 什么是线程间数据共享
在多线程编程中,当多个线程需要访问和操作同一个数据对象时,就形成了线程间的数据共享。这种共享可以是:
- 显式共享:通过公共变量或共享对象
- 隐式共享:通过闭包或回调引用
```java
// 典型共享示例
public class SharedData {
    public static int counter = 0;  // 静态变量共享
}
Java内存模型规定了线程如何与内存交互: - 主内存:存储共享变量 - 工作内存:每个线程私有的内存空间 - happens-before原则:保证可见性的核心规则
当多个线程无序访问共享数据时,程序的正确性依赖于线程执行的时序。
// 竞态条件示例
if (counter == 5) {
    counter++;  // 非原子操作
}
由于CPU缓存的存在,线程可能看不到其他线程对共享变量的修改。
同步机制带来的额外成本: - 上下文切换 - 内存屏障指令 - 锁竞争
class GlobalData {
    static volatile int globalCounter;
}
class SharedInstance {
    private int value;
    
    public synchronized void increment() {
        value++;
    }
}
class DataHolder {
    private Object data;
    
    public void process(Consumer<Object> processor) {
        processor.accept(data);
    }
}
| 非线程安全类 | 线程安全替代 | 
|---|---|
| ArrayList | CopyOnWriteArrayList | 
| HashMap | ConcurrentHashMap | 
| HashSet | ConcurrentHashSet | 
BlockingQueue<String> queue = new LinkedBlockingQueue<>(10);
// 生产者
queue.put("item"); 
// 消费者
String item = queue.take();
ConcurrentMap<String, AtomicInteger> map = new ConcurrentHashMap<>();
map.computeIfAbsent("key", k -> new AtomicInteger(0)).incrementAndGet();
// 方法同步
public synchronized void syncMethod() {}
// 块同步
synchronized(lockObject) {
    // 临界区代码
}
Lock lock = new ReentrantLock();
try {
    lock.lock();
    // ...
} finally {
    lock.unlock();
}
ReadWriteLock rwLock = new ReentrantReadWriteLock();
// 读锁
rwLock.readLock().lock();
// 写锁
rwLock.writeLock().lock();
AtomicInteger atomicInt = new AtomicInteger(0);
atomicInt.incrementAndGet();
比较并交换(Compare-And-Swap)的底层实现:
// 伪代码
int compare_and_swap(int* reg, int oldval, int newval) {
    int old_reg_val = *reg;
    if (old_reg_val == oldval)
        *reg = newval;
    return old_reg_val;
}
LongAdder adder = new LongAdder();
adder.increment();
long sum = adder.sum();
volatile boolean shutdownRequested;
public void shutdown() {
    shutdownRequested = true;
}
| 特性 | volatile | synchronized | 
|---|---|---|
| 原子性 | 无 | 有 | 
| 可见性 | 有 | 有 | 
| 互斥性 | 无 | 有 | 
ThreadLocal<SimpleDateFormat> dateFormat = 
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
必须注意remove()的调用:
try {
    // 使用ThreadLocal
} finally {
    threadLocal.remove();
}
JDK 8之前:Segment分段锁 JDK 8+:CAS + synchronized优化
// 不好
synchronized(this) {
    // 大量代码
}
// 优化
private final Object specificLock = new Object();
synchronized(specificLock) {
    // 最小临界区
}
// 危险代码
synchronized(lockA) {
    synchronized(lockB) {
        // ...
    }
}
| 场景 | 推荐方案 | 
|---|---|
| 计数器 | AtomicLong/LongAdder | 
| 状态标志 | volatile | 
| 集合共享 | ConcurrentHashMap | 
| 复杂同步 | ReentrantLock | 
本文完整代码示例及扩展讨论详见:GitHub仓库链接 最后更新:2023年6月15日 “`
注:实际文章需要扩展每个章节的详细内容、更多代码示例、性能测试数据、图表说明等以达到万字规模。以上为完整框架和核心内容展示。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。