java 中的 volatile AND synchronized

简介: 这个关键字在实际开发中用的比较少, 但是对多线程编程又有很大的帮助

要了解 Java中的 volatile 首席要从线程间通讯开始

image

概念:

  1. 对于声明了 volatile 的变量进行写的操作时, JVM 会向处理器(CPU) 发送一条 Lock 前缀的指令, 会将这个变量所在缓存行的数据写回到系统内存(主内存)
  2. 在多处理器的情况下, 保持各个处理器缓存一致性的特点, 就会实现缓存一致性协议
  3. 但是,就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题。
  4. 每个处理器通过嗅探在主内存上传播的数据来检查自己缓存的值是不是过期了
  5. 当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,就会重新从系统内存中把数据读到处理器缓存里。
  6. 总之 volatile 做的事情是: 在多线程执行中保证共享对象的一致性


synchronized

image

public class Demo {
        
    private static int i = 0;    
    
    public static void main(String[] args) {
        synchronized(Demo.class) {
            i++;
        }
    }
    
}

javap -c -v Demo.class : 结果

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: ldc           #2                  // class Demo
         2: dup
         3: astore_1
         4: monitorenter
         5: getstatic     #3                  // Field i:I
         8: iconst_1
         9: iadd
        10: putstatic     #3                  // Field i:I
        13: aload_1
        14: monitorexit
        15: goto          23
        18: astore_2
        19: aload_1
        20: monitorexit
        21: aload_2
        22: athrow
        23: return
      Exception table:
         from    to  target type
             5    15    18   any
            18    21    18   any
      LineNumberTable:
        line 6: 0
        line 7: 5
        line 8: 13
        line 9: 23
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 18
          locals = [ class "[Ljava/lang/String;", class java/lang/Object ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 4
monitorenter     : 进入并获取对象监视器
monitorexit      : 释放并退出对象监视器
  1. synchronized获得并释放监视器, 如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行。
  2. volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。
  3. 显然synchronized要比volatile消耗更多资源。
目录
相关文章
|
1月前
|
存储 Java 程序员
记一次synchronized锁字符串引发的坑兼再谈Java字符串
记一次synchronized锁字符串引发的坑兼再谈Java字符串
21 2
|
18天前
|
设计模式 安全 Java
Java并发编程实战:使用synchronized关键字实现线程安全
【4月更文挑战第6天】Java中的`synchronized`关键字用于处理多线程并发,确保共享资源的线程安全。它可以修饰方法或代码块,实现互斥访问。当用于方法时,锁定对象实例或类对象;用于代码块时,锁定指定对象。过度使用可能导致性能问题,应注意避免锁持有时间过长、死锁,并考虑使用`java.util.concurrent`包中的高级工具。正确理解和使用`synchronized`是编写线程安全程序的关键。
|
3月前
|
存储 Java 编译器
解密Java中神奇的Synchronized关键字
解密Java中神奇的Synchronized关键字
|
1月前
|
安全 Java
Java并发编程:Synchronized及其实现原理
Java并发编程:Synchronized及其实现原理
25 4
|
5天前
|
安全 Java 开发者
Java并发编程:深入理解Synchronized关键字
【4月更文挑战第19天】 在Java多线程编程中,为了确保数据的一致性和线程安全,我们经常需要使用到同步机制。其中,`synchronized`关键字是最为常见的一种方式,它能够保证在同一时刻只有一个线程可以访问某个对象的特定代码段。本文将深入探讨`synchronized`关键字的原理、用法以及性能影响,并通过具体示例来展示如何在Java程序中有效地应用这一技术。
|
7天前
|
Java
浅谈Java的synchronized 锁以及synchronized 的锁升级
浅谈Java的synchronized 锁以及synchronized 的锁升级
8 0
|
7天前
|
存储 缓存 安全
Java并发基础之互斥同步、非阻塞同步、指令重排与volatile
在Java中,多线程编程常常涉及到共享数据的访问,这时候就需要考虑线程安全问题。Java提供了多种机制来实现线程安全,其中包括互斥同步(Mutex Synchronization)、非阻塞同步(Non-blocking Synchronization)、以及volatile关键字等。 互斥同步(Mutex Synchronization) 互斥同步是一种基本的同步手段,它要求在任何时刻,只有一个线程可以执行某个方法或某个代码块,其他线程必须等待。Java中的synchronized关键字就是实现互斥同步的常用手段。当一个线程进入一个synchronized方法或代码块时,它需要先获得锁,如果
24 0
|
2月前
|
存储 安全 Java
[Java]volatile关键字
[Java]volatile关键字
30 0
|
2月前
|
存储 缓存 Java
Java volatile关键字-单例模式的双重锁为什么要加volatile
Java volatile关键字--单例模式的双重锁为什么要加volatile
51 10
|
2月前
|
Java 编译器 程序员
Volatile:Java并发编程的隐形英雄
Volatile:Java并发编程的隐形英雄
25 0