volatile关键字的作用

在Java并发编程中,volatilesynchronized 是两种常见的同步机制。它们虽然都可以用于多线程环境下的变量同步,但在语义和使用场景上有显著区别。以下是详细的对比与补充:

volatile关键字

volatile 关键字用于声明共享变量,并为其赋予两层语义:

  1. 可见性保证

    • 当一个线程修改了 volatile 变量的值,新值会立即被刷新到主内存中,并且其他线程读取这个变量时可以立即获得最新的值。
    • 具体来说,当一个线程写入 volatile 变量时,会强制将缓存中的数据刷新到主内存;当一个线程读取 volatile 变量时,会强制从主内存中读取数据。
  2. 禁止指令重排序

    • volatile 变量在写操作和读操作时,会在指令层面加上内存屏障(Memory Barrier),以禁止对这些操作进行重排序,从而避免因重排序带来的数据不一致问题。

synchronized关键字

synchronized 关键字可以用于方法或者代码块,实现同步。其主要特点包括:

  1. 可见性和原子性保证

    • synchronized 不仅能保证变量的可见性,还能保证变量操作的原子性。
    • 进入 synchronized 方法或代码块的线程会持有锁,任何其他线程在锁被释放前都无法进入同一个 synchronized 方法或代码块。
  2. 线程阻塞

    • 使用 synchronized 关键字时,如果一个线程获取了锁,其他线程试图获取这把锁时会被阻塞,直到锁被释放。

对比总结

  1. 使用层级

    • volatile:只能用于变量级别。
    • synchronized:可以用于方法级别和代码块级别(包括类和实例级别)。
  2. 功能

    • volatile:只能保证可见性,不能保证操作的原子性。例如,volatile 不能保证复合操作(如i++)的原子性。
    • synchronized:不仅能保证可见性,还能保证操作的原子性。
  3. 性能

    • volatile:不会造成线程阻塞,性能开销较小,因为它不会涉及上下文切换和调度。
    • synchronized:可能会造成线程阻塞,导致上下文切换和调度,性能开销相对较大。
  4. 编译器优化

    • volatile:变量不会被编译器优化,必须每次都从主内存中读取。
    • synchronized:在锁释放之前,编译器和处理器都不能对其进行优化,但锁释放之后,相关代码仍可被优化。
      复制代码
      public class VolatileExample {
          private volatile boolean flag = false;
      
          public void writer() {
              flag = true;  // 写操作
          }
      
          public void reader() {
              if (flag) {  // 读操作
                  // 进行操作
              }
          }
      }
      复制代码
      复制代码
      public class SynchronizedExample {
          private int count = 0;
      
          public synchronized void increment() {
              count++;  // 原子性操作
          }
      
          public synchronized int getCount() {
              return count;  // 可见性保证
          }
      }
      复制代码

       

posted @   Stars-125  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示