您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。