Volatile关键字与Java原子性的迷宫之旅
创始人
2024-11-14 11:05:34
0次

在Java并发编程的领域中,有一种看似简单却蕴藏深意的关键字——volatile。它如同一把钥匙,打开了数据一致性与线程间通信的大门。但volatile并非全能,尤其是在原子性面前,它有着自己的局限性。本文将带你穿越迷宫,探索volatile的真谛及其与原子性的关系。

Volatile的面纱:可见性与有序性

Volatile关键字的核心作用在于确保变量的可见性与有序性。所谓可见性,指的是当一个线程修改了某个volatile变量后,其他线程能够立即看到这一变化。有序性则保证了指令不会被处理器或编译器重排序,从而避免了某些类型的竞争条件。

示例代码:

public class VolatileVisibility {     public static volatile boolean ready = false;     public static int number = 0;      public static void main(String[] args) throws InterruptedException {         Thread writerThread = new Thread(() -> {             number = 42;             ready = true;         });          Thread readerThread = new Thread(() -> {             while (!ready) {                 Thread.yield();             }             System.out.println(number); // 应该输出42         });          writerThread.start();         readerThread.start();          writerThread.join();         readerThread.join();     } } 

在这个例子中,如果没有volatile修饰符,number的更新可能不会被readerThread及时发现,导致输出错误的结果。但加上volatile后,readerThread将能够正确读取到writerThread写入的新值。

原子性的迷雾:Volatile的盲区

虽然volatile能提供可见性和有序性,但它并不能保证原子性。原子性意味着一个操作要么完全执行,要么完全不执行,不会被中断。例如,考虑下面的代码片段:

示例代码:

public class VolatileNonAtomicity {     public static volatile int count = 0;      public static void main(String[] args) throws InterruptedException {         Thread[] threads = new Thread[10];         for (int i = 0; i < threads.length; i++) {             threads[i] = new Thread(() -> {                 for (int j = 0; j < 1000; j++) {                     count++; // 这个操作不是原子的                 }             });             threads[i].start();         }          for (Thread t : threads) {             t.join();         }          System.out.println("Expected: 10000, Actual: " + count);     } } 

尽管count是volatile的,但count++操作并非原子的,因此多个线程同时进行加法操作时,可能会得到比预期少的结果。这是因为count++实际上是由读取、计算、写回三个步骤组成的,而在多线程环境下,这些步骤可能被不同的线程交错执行。

原子性的解决方案:Java并发类库

为了弥补volatile在原子性方面的不足,Java提供了java.util.concurrent.atomic包,其中包含了一系列原子类,如AtomicInteger、AtomicLong等,它们利用内部的锁或其他同步机制来保证原子性。

示例代码:

import java.util.concurrent.atomic.AtomicInteger;  public class AtomicSafety {     public static AtomicInteger atomicCount = new AtomicInteger(0);      public static void main(String[] args) throws InterruptedException {         Thread[] threads = new Thread[10];         for (int i = 0; i < threads.length; i++) {             threads[i] = new Thread(() -> {                 for (int j = 0; j < 1000; j++) {                     atomicCount.incrementAndGet(); // 原子性操作                 }             });             threads[i].start();         }          for (Thread t : threads) {             t.join();         }          System.out.println("Expected: 10000, Actual: " + atomicCount.get());     } } 

在这个版本中,atomicCount使用AtomicInteger,其incrementAndGet()方法是原子性的,从而保证了所有线程操作的完整性,输出结果将始终等于预期。

相关内容

热门资讯

每日必看教程!微乐小程序黑科技... 每日必看教程!微乐小程序黑科技免费(辅助器),微信小程序怎么开挂(有辅助挂教学)1、让任何用户在无需...
今日公布!微乐小程序免费黑科技... 今日公布!微乐小程序免费黑科技(透视器),微信小程序微乐辅助器教程图片(有辅助挂辅教程)1、完成微乐...
安装程序教程!微乐小程序辅助工... 安装程序教程!微乐小程序辅助工具(透视器),微乐小程序黑科技辅助工具2026最新推荐(证实有辅助挂)...
我来教大家!微乐小程序黑科技免... 我来教大家!微乐小程序黑科技免费(辅助),微信小程序微乐安徽辅助苹果(确实有辅助挂)1)微乐小程序黑...
热点推荐!微乐小程序黑科技免费... 热点推荐!微乐小程序黑科技免费(辅助),微信小程序透视微乐(竟然有辅助挂)1、微乐小程序黑科技免费破...
揭秘几款!微乐小程序免费黑科技... 揭秘几款!微乐小程序免费黑科技(辅助),微信微乐陕西小程序破解器(有辅助挂辅助)揭秘几款!微乐小程序...
重大通报!微乐小程序免费黑科技... 重大通报!微乐小程序免费黑科技(辅助),微乐游戏辅助脚本安装(有辅助挂辅助)1、每一步都需要思考,不...
玩家交流!微乐小程序免费黑科技... 玩家交流!微乐小程序免费黑科技(作弊器),微乐家乡官方app下载(有辅助挂辅教程)1)微乐小程序免费...
教程攻略!微乐小程序黑科技免费... 教程攻略!微乐小程序黑科技免费(开挂),微乐小程序游戏破解器下载(有辅助挂方式)1、不需要AI权限,...
终于清楚!微乐小程序黑科技免费... 终于清楚!微乐小程序黑科技免费(作弊器),微乐小程序辅助教程(有辅助挂秘籍)1、用户打开应用后不用登...