并发的三大特性之一:有序性

在并发编程中,除了原子性和可见性,有序性也是很重要的一个特性。有序性指的是程序执行的顺序按照代码的先后顺序执行,对于单个线程来说,这是显而易见的,因为在单线程中,程序的执行顺序就是代码的排列顺序。

为什么有序性会成为问题?

在并发环境下,事情变得复杂起来。有两种类型的有序性问题需要考虑:

  1. 编译器优化带来的有序性问题:为了提高性能,编译器和处理器常常会对指令序列做重排序。重排序是在不改变单线程程序语义的情况下,通过改变指令的执行顺序来获取更优性能的一种技术。

  2. 内存系统的有序性问题:由于现代计算机使用了缓存系统,并且多处理器通常有自己的本地缓存,这可能会导致不同的处理器看到不一致的内存视图。

如何保证有序性?

Java Memory Model (JMM) 提供了一系列的内存屏障指令(happens-before规则)来保障有序性。

  1. **volatile关键字:**当变量被声明为volatile后,编译器和运行时都会注意到这个变量是共享的,因此不会将这个变量上的操作与其他内存操作进行重排序。同时,volatile变量的写操作happens-before后续对同一个变量的读操作,保障了有序性。

  2. **synchronizedLock机制:**在synchronized同步块或方法内部,所有操作几乎是串行化执行的,同一时刻只允许一个线程进入代码块进行操作。释放锁的happens-before获取同一个锁。

  3. **final关键字:**在Java内存模型中,被final修饰的字段,一旦初始化完成,并且构造函数退出,不允许对他们进行重排序。这保证了在访问一个final字段时,可以看到由构造函数对这个final字段的所有赋值操作。

代码举例

假设有以下代码:

int a = 10; // 语句1
int b = 20; // 语句2

如果这两条语句在没有同步的情况下被多线程访问,处理器或者JIT编译器可能会对这两条语句进行重排序,改变它们的执行顺序。而如果我们希望按照顺序执行,可以使用synchronized关键字或volatile关键字,如:

volatile int a = 10; // 语句1
volatile int b = 20; // 语句2

使用volatile修饰后,语句1和语句2在内存中的顺序就如编码时的顺序一样,禁止进行指令重排序。

总的来说,有序性保证了程序在执行时,按照代码的预期顺序执行操作,而不会因为编译器或处理器优化导致执行顺序的混乱,这对于并发程序的正确性至关重要。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java奋斗者

听说打赏我的人再也不会有BUG

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值