300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > java并发编程(1)--线程 可见性 volatile怎么用

java并发编程(1)--线程 可见性 volatile怎么用

时间:2021-03-11 05:26:13

相关推荐

java并发编程(1)--线程 可见性 volatile怎么用

一、每个Java线程都有⾃⼰的⼯作内存

操作数据,⾸先从主内存中读,得到⼀份拷⻉,操作完毕后再写回到主内存。

不同的线程间⽆法访问对⽅的⼯作内存,线程间的通信 (传值)必须通过主内存来完成

二、不同的线程间⽆法访问对⽅的⼯作内存

package thread;import java.util.concurrent.TimeUnit;/*** volitale关键字是Java提供的⼀种轻量级同步机制。* 它能够保证可⻅性和有序性* 但是不能保证原⼦性* 禁⽌指令重排*/class MyData {int number = 0;// volatile int number = 0;public void setTo60() {this.number = 60;}}public class VolatileDemo {public static void main(String[] args) {volatileVisibilityDemo();}// volatile可以保证可⻅性,及时通知其它线程主物理内存的值已被修改private static void volatileVisibilityDemo() {System.out.println("可⻅性测试");MyData myData = new MyData();//资源类// 启动⼀个线程操作共享数据new Thread(() -> {System.out.println(Thread.currentThread().getName() + "\t 执⾏");try {TimeUnit.SECONDS.sleep(3);// 更新number的值myData.setTo60();System.out.println(Thread.currentThread().getName() + "\t 更新number值: " + myData.number);}catch (InterruptedException e) {e.printStackTrace();}}, "ThreadA").start();// main线程,获取共享变量改变后的结果while (myData.number == 0) {// main线程持有共享数据的拷⻉,⼀直为0// 若number的值一直为0,说明main线程没有得到共享变量改变值的通知}System.out.println(Thread.currentThread().getName() + "\t main获取 number值: " + myData.number);}}

虽然⼀个线程把number修改成了60,但是main线程持有的仍然是最开始的0,所以⼀直循环,程序不会结束。

三、如果对变量添加了volatile修饰

package thread;import java.util.concurrent.TimeUnit;/*** volitale关键字是Java提供的⼀种轻量级同步机制。* 它能够保证可⻅性和有序性* 但是不能保证原⼦性* 禁⽌指令重排*/class MyData {// int number = 0;volatile int number = 0;public void setTo60() {this.number = 60;}}public class VolatileDemo {public static void main(String[] args) {volatileVisibilityDemo();}// volatile可以保证可⻅性,及时通知其它线程主物理内存的值已被修改private static void volatileVisibilityDemo() {System.out.println("可⻅性测试");MyData myData = new MyData();//资源类// 启动⼀个线程操作共享数据new Thread(() -> {System.out.println(Thread.currentThread().getName() + "\t 执⾏");try {TimeUnit.SECONDS.sleep(3);// 更新number的值myData.setTo60();System.out.println(Thread.currentThread().getName() + "\t 更新number值: " + myData.number);}catch (InterruptedException e) {e.printStackTrace();}}, "ThreadA").start();// main线程,获取共享变量改变后的结果while (myData.number == 0) {// main线程持有共享数据的拷⻉,⼀直为0// 若number的值一直为0,说明main线程没有得到共享变量改变值的通知// System.out.println(Thread.currentThread().getName() + "\t 等待。。。 ");}System.out.println(Thread.currentThread().getName() + "\t main获取 number值: " + myData.number);}}

可⻅某个线程对number的修改,会⽴刻反映到主内存上。

每个线程是独立的,但是线程对变量的所有操作都必须在拷贝到自己的工作内存中进行,而不能直接读写主内存中的变量。

不同线程之间也无法直接访问对方工作内存中的变量。

当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去主内存中读取新值,所以可见性是立即可见的意思。

如果没有加volatile,线程A修改了,还没来得及写回主内存,另一个线程也要修改,但是他没保证可见性,去主内存没拿到线程A修改的最新的值,就会出现问题。

四、System.out.println()有锁

即使没有volitale修饰

package thread;import java.util.concurrent.TimeUnit;/*** volitale关键字是Java提供的⼀种轻量级同步机制。* 它能够保证可⻅性和有序性* 但是不能保证原⼦性* 禁⽌指令重排*/class MyData {int number = 0;// volatile int number = 0;public void setTo60() {this.number = 60;}}public class VolatileDemo {public static void main(String[] args) {volatileVisibilityDemo();}// volatile可以保证可⻅性,及时通知其它线程主物理内存的值已被修改private static void volatileVisibilityDemo() {System.out.println("可⻅性测试");MyData myData = new MyData();//资源类// 启动⼀个线程操作共享数据new Thread(() -> {System.out.println(Thread.currentThread().getName() + "\t 执⾏");try {TimeUnit.SECONDS.sleep(3);// 更新number的值myData.setTo60();System.out.println(Thread.currentThread().getName() + "\t 更新number值: " + myData.number);}catch (InterruptedException e) {e.printStackTrace();}}, "ThreadA").start();// main线程,获取共享变量改变后的结果while (myData.number == 0) {// main线程持有共享数据的拷⻉,⼀直为0// 若number的值一直为0,说明main线程没有得到共享变量改变值的通知System.out.println(Thread.currentThread().getName() + "\t 等待。。。 ");}System.out.println(Thread.currentThread().getName() + "\t main获取 number值: " + myData.number);}}

结果

原因 synchronized

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。