×

volatile如何保证可见性

volatile如何保证可见性(为什么voliter修饰能够实现线程安全,请简述)

admin admin 发表于2023-10-22 07:19:21 浏览38 评论0

抢沙发发表评论

本文目录

为什么voliter修饰能够实现线程安全,请简述

volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。

这句话可以理解出两点:

  1. 加了volatile之后编译器不会对其进行优化。因为你的一句话,并不是一条指令,会被编译成多条计算机指令,一般计算机会对其进行优化和重新排序,这就不能保证还是原来的执行顺序也就不能保证执行结果是安全的,加了volatile之后编译器不会对其优化重排序。

  2. 可见性。每个线程都保存有公共变量的副本,变量赋值也不是你想象中的立刻就能被其他线程看到,因为其他线程的副本可能没有更新。加了volatile之后,当其他线程要读取该变量时,会强制从主内存中读取并刷新副本,保证更新后的值一定能被其他线程读取到。

    最后、volatile只能保证可见性,保证读取是线程安全的,并不能保证写入的安全性。适用于单线程写,多线程读。

线程间通信有哪些方式

线程间通信方式有:

1、volatile

volatile有两大特性,一是可见性,二是有序性,禁止指令重排序,其中可见性就是可以让线程之间进行通信。volatile语义保证线程可见性有两个原则保证:

(1)所有volatile修饰的变量一旦被某个线程更改,必须立即刷新到主内存。

(2)所有volatile修饰的变量在使用之前必须重新读取主内存的值。

2、等待/通知机制

等待通知机制是基于wait和notify方法来实现的,在一个线程内调用该线程锁对象的wait方法,线程将进入等待队列进行等待直到被通知或者被唤醒。

3、join方式

join其实合理理解成是线程合并,当在一个线程调用另一个线程的join方法时,当前线程阻塞等待被调用join方法的线程执行完毕才能继续执行,所以join的好处能够保证线程的执行顺序。

但是如果调用线程的join方法其实已经失去了并行的意义,虽然存在多个线程,但是本质上还是串行的,最后join的实现其实是基于等待通知机制的。

4、threadLocal

threadLocal方式的线程通信,不像以上三种方式是多个线程之间的通信,它更像是一个线程内部的通信,将当前线程和一个map绑定,在当前线程内可以任意存取数据,减省了方法调用间参数的传递。

线程特点:

1、轻型实体

线程中的实体基本上不拥有系统资源,只是有一点必不可少的、能保证独立运行的资源。线程的实体包括程序、数据和TCB。线程是动态概念,它的动态特性由线程控制块TCB(Thread Control Block)描述。

2、独立调度和分派的基本单位

在多线程OS中,线程是能独立运行的基本单位,因而也是独立调度和分派的基本单位。由于线程很“轻”,故线程的切换非常迅速且开销小(在同一进程中的)。

3、可并发执行

在一个进程中的多个线程之间,可以并发执行,甚至允许在一个进程中所有线程都能并发执行;同样,不同进程中的线程也能并发执行,充分利用和发挥了处理机与外围设备并行工作的能力。

4、共享进程资源

在同一进程中的各个线程,都可以共享该进程所拥有的资源,这首先表现在:所有线程都具有相同的地址空间(进程的地址空间),这意味着,线程可以访问该地址空间的每一个虚地址。

此外,还可以访问进程所拥有的已打开文件、定时器、信号量机构等。由于同一个进程内的线程共享内存和文件,所以线程之间互相通信不必调用内核。

请教一个java多线程的可见问题

第一:你那个thread未必能在while循环判断条件之前执行,不是写在前面就一定能在前面先执行第二:volatile可以保证可见性,不加也并代表一定没有可见性,运行中很多种情况会导致线程去主存来刷新工作内存中的变量内容。举个例子就是并发下的 int i++操作,不加volatile一样可以累计只是累计值差一点,说明别的线程是可以看到其他线程修改后的值的。不然每个人看到都是0,然后写会内存永远都是1。‍一般来讲,如果不是那种计算密集型任务,例如空循环这种,A线程在空循环时很难读到别的线程变量改变后的值。你可以理解为线程A太忙了以至于没空刷新自己的工作内存的变量值,一旦有空就会去刷新。所以如果你想中断一个线程的循环,一般都是用whil(flag){},flag设置为volatile变量,保证可见性,否则flag改变后,另一个线程未必能立刻读的到改变从而立刻响应停止。

java中volatile怎么使用的

我的理解是, volatile关键字,保证此变量对所有线程的可见性,每条线程使用此类型变量前都需要先刷新。放到线程A中boolean a;boolean b;a=bChanged;b=!bChanged;System.out.println(a);System.out.println(b);if (a==b) {System.out.println(111);System.exit(0);} bchange==!bchange,因为有Volatile的存在,读取都会从主存中读取,但是读取bchange的时候可能是true,但线程b改变后,导致第二个!bchange读取的值是改变过后的值线程安全必须满足原子性,可见性,有序性,Voliate只能保证可见性和有序性。无法满足操作是原子性