线程有有序性和可见性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程有有序性和可见性相关的知识,希望对你有一定的参考价值。

多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变量来实现。

在多个线程之间共享类的一个对象,这个对象是被创建在主内存(堆内存)中,每个线程都有自己的工作内存(线程栈),工作内存存储了主内存对象的一个副本,当线程操作对象时,首先从主内存复制对象到工作内存中,然后执行代码改变了值,最后用工作内存刷新主内存。

当一个对象在多个内存中都存在副本时,如果一个内存修改了共享变量,其它线程也应该能够看到被修改后的值,此为可见性

多个线程执行时,CPU对线程的调度是随机的,我们不知道当前程序被执行到哪步就切换到了下一个线程。为保证线程有序执行此为有序性

 

使用synchronized修饰的方法或者代码块可以看成是一个原子操作

        每个锁对象(JLS中叫monitor)都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程,当一个线程被唤醒(notify)后,才会进入到就绪队列,等待CPU的调度,反之,当一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒。看我们的例子,当第一个线程执行输出方法时,获得同步锁,执行输出方法,恰好此时第二个线程也要执行输出方法,但发现同步锁没有被释放,第二个线程就会进入就绪队列,等待锁被释放。一个线程执行互斥代码过程如下:

        1. 获得同步锁;

        2. 清空工作内存;

        3. 从主内存拷贝对象副本到工作内存;

        4. 执行代码(计算或者输出等)

        5. 刷新主内存数据;

        6. 释放同步锁。

        所以,synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性。

 

volatile是第二种Java多线程同步的机制,一个变量可以被volatile修饰,在这种情况下内存模型(主内存和线程工作内存)确保所有线程可以看到一致的变量值。

 

以上是关于线程有有序性和可见性的主要内容,如果未能解决你的问题,请参考以下文章

原子性、可见性、有序性

Java线程安全:可见性,原子性,有序性

Java多线程安全可见性和有序性之Volatile

线程有有序性和可见性

并发编程之原子性可见性有序性的简单理解

线程执行的几种特性(共享性互斥性原子性可见性有序性)