java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java synchronized有序性

浅谈Java并发编程之synchronized有序性误区

作者:Johnny Lnex

本文主要介绍了浅谈Java并发编程之synchronized有序性误区,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

许多开发者误以为synchronized能完全禁止指令重排序,而实际上它仅能保证线程间的操作顺序,真正禁用重排序需依赖volatile

一、synchronized的有序性保证

synchronized通过锁机制间接保证多线程操作的顺序性,具体规则基于 Happens-Before 原则

示例:线程间可见性与顺序性

public class SynchronizedOrderDemo {
    private int value = 0;
    private final Object lock = new Object();

    // 线程A:写操作
    public void write() {
        synchronized (lock) {
            value = 42; // 写操作
        }
    }

    // 线程B:读操作
    public int read() {
        synchronized (lock) {
            return value; // 保证读到42
        }
    }
}

执行顺序

  1. 线程A先获取锁,写value = 42,释放锁。
  2. 线程B获取锁后,一定能读到value = 42

二、synchronized无法禁止指令重排序

尽管synchronized保证了线程间的顺序性,但同步块内部的指令仍可能被重排序(只要不影响单线程执行结果)。这种重排序对单线程透明,但可能导致多线程问题。

示例:同步块内的指令重排序

synchronized (lock) {
    int a = 1;  // 操作1
    int b = 2;  // 操作2
}

1.volatile的禁止重排序机制

volatile通过插入内存屏障,直接限制编译器和处理器的指令重排序:

示例:volatile禁止对象初始化的重排序

// 双重检查锁定(DCL)单例模式
public class Singleton {
    private static volatile Singleton instance; // volatile禁止重排序

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton(); // 初始化操作
                }
            }
        }
        return instance;
    }
}

三、对比

特性synchronizedvolatile
线程顺序性保证多线程间的操作顺序(通过锁的Happens-Before规则)不直接保证多线程顺序,仅确保单变量操作顺序
指令重排序允许同步块内部的重排序(单线程语义下)禁止与volatile变量相关的重排序
可见性通过锁释放-获取保证所有变量的可见性仅保证volatile变量的可见性
原子性保证同步块内操作的原子性不保证复合操作的原子性(如i++)
性能开销较高(涉及用户态与内核态切换)较低(仅内存屏障开销)

四、常见误区

1. 误区:synchronized能完全禁止指令重排序

2. 误区:volatile可替代锁

到此这篇关于浅谈Java并发编程之synchronized有序性误区的文章就介绍到这了,更多相关Java synchronized有序性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

到此这篇关于浅谈Java并发编程之synchronized有序性误区的文章就介绍到这了,更多相关Java synchronized有序性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文