Java并发08:并发编程的三大核心问题 - 原子性、可见性、有序性

引言:为什么synchronized能解决所有问题? // volatile只解决部分问题 private volatile int count = 0; count++; // 仍然不安全! // synchronized解决所有问题 private int count = 0; public synchronized void increment() { count++; // 安全 } 为什么? 关键在于理解并发编程的三大核心问题: 原子性(Atomicity) 可见性(Visibility) 有序性(Ordering) 一、原子性(Atomicity) 1.1 什么是原子性? 定义:一个操作或多个操作,要么全部执行且执行过程不被打断,要么都不执行。 int a = 10; // ✅ 原子操作 a++; // ❌ 非原子操作(3条指令) 1.2 哪些操作是原子的? 原子操作: // ✅ 基本类型的读写(long/double除外) int a = 1; boolean b = true; // ✅ 引用类型的读写 Object obj = new Object(); // ✅ volatile变量的读写 volatile int count = 0; count = 1; // 原子的 非原子操作: // ❌ long/double(64位,需要两次操作) long value = 123L; // 非原子的(未加volatile) // ❌ 复合操作 count++; // read-modify-write array[index]++; // 非原子 // ❌ check-then-act if (map.get(key) == null) { map.put(key, value); // 竞态条件 } 1.3 如何保证原子性? 方式1:synchronized public synchronized void increment() { count++; // 整个方法是原子的 } 方式2:Lock private Lock lock = new ReentrantLock(); public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } 方式3:原子类 private AtomicInteger count = new AtomicInteger(0); public void increment() { count.incrementAndGet(); // 原子操作 } 二、可见性(Visibility) 2.1 什么是可见性? 定义:当一个线程修改了共享变量,其他线程能够立即看到这个修改。 ...

2025-11-20 · maneng

事务与原子性:MULTI/EXEC命令详解

引言 在关系型数据库中,事务是保证数据一致性的重要手段(ACID)。那么Redis有事务吗? 答案是:有,但不完全是你理解的那种事务。 Redis的事务更像是批量命令,提供的是有限的原子性,而不是ACID中的那种强事务。 一、Redis事务的本质 1.1 什么是Redis事务? Redis事务是一组命令的集合,这些命令会: 顺序执行:按队列顺序依次执行 不被打断:执行期间不会插入其他客户端的命令 要么全执行,要么全不执行(有限制) 示例: 127.0.0.1:6379> MULTI # 开始事务 OK 127.0.0.1:6379> SET account:1 100 QUEUED 127.0.0.1:6379> SET account:2 200 QUEUED 127.0.0.1:6379> EXEC # 执行事务 1) OK 2) OK 1.2 Redis事务 vs 关系型数据库事务 特性 MySQL事务 Redis事务 原子性(A) ✅ 全部成功或回滚 ⚠️ 部分支持 一致性(C) ✅ 约束检查 ⚠️ 无约束 隔离性(I) ✅ 多种隔离级别 ⚠️ 无隔离级别 持久性(D) ✅ 提交后持久化 ⚠️ 取决于配置 回滚 ✅ 支持 ❌ 不支持 关键区别: MySQL: BEGIN; UPDATE account SET balance = balance - 100 WHERE id = 1; UPDATE account SET balance = balance + 100 WHERE id = 2; COMMIT; -- 要么都成功,要么都回滚 Redis: MULTI DECR account:1:balance 100 INCR account:2:balance 100 EXEC -- 命令出错也不回滚! 二、事务命令详解 2.1 MULTI - 开始事务 127.0.0.1:6379> MULTI OK # 此后的命令不会立即执行,而是进入队列 127.0.0.1:6379> SET key1 "value1" QUEUED # 入队 127.0.0.1:6379> SET key2 "value2" QUEUED 2.2 EXEC - 执行事务 127.0.0.1:6379> EXEC 1) OK # SET key1的返回值 2) OK # SET key2的返回值 # 所有命令顺序执行,一次性返回结果 2.3 DISCARD - 取消事务 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET key1 "value1" QUEUED 127.0.0.1:6379> DISCARD # 取消事务 OK # 队列中的命令全部丢弃,不执行 127.0.0.1:6379> GET key1 (nil) # 没有执行 2.4 WATCH - 乐观锁 问题场景: ...

2025-01-21 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...