当前位置:网站首页>volatile的解构| 社区征文
volatile的解构| 社区征文
2022-06-11 22:35:00 【InfoQ】

volatile :
一、可见性
import java.util.concurrent.TimeUnit;
class volatileTest1{
//加volatile可以看见结果
volatile int number=0;//成员变量默认为0
public void addTo60(){
//将number变成60
this.number=60;
}
}
public class volatileDemo {
//如何理解这个volatile的保证可见性:
/*
* 可见性: 保证在线程使用的过程中,将数据修改后,及时的通知其他线程更新数据;
*
* demo的设计原理: (需要添加的是一个睡眠时间3-不然结果会出错误)
* 我们运行nto60的方法--看main线程是否能获得已经变化了的数值number
* 否则将循环下去
* */
public static void main(String[] args) {
//1.资源类的初始化
volatileTest1 volatileTest1=new volatileTest1();
new Thread(()->{
System.out.println(Thread.currentThread().getName()+":come in"+volatileTest1.number);
//这里必须要睡3秒--不然的结果就是main线程也会同步,因为线程的运行速度太快啦
try {
//休眠3秒钟
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
}
//2.操作高内聚的方法nTo60
volatileTest1.addTo60();
System.out.println(Thread.currentThread().getName()+":ture后的"+volatileTest1.number);
},"web").start();
//上述的web线程已经将数据变成60;
//测试main线程是否感知到;
while (volatileTest1.number==0){
//就一直循环。什么都不会打印出来
}
System.out.println(Thread.currentThread().getName() +":"+volatileTest1.number);
//表示main线程也知晓了number的变化---满足了volatile的可见性的需求
/*
*
* web:come in0
web:ture后的60
main:60
*
* */
}
}
2.不保证原子性:


1. 细说a++的运行过程:


2. 怎么解决volatile的不保证原子性情况:
//AtomicInteger是 java.util.concurrent.atomic原子包写的类
AtomicInteger atomicInteger=new AtomicInteger();
public void addMyatomic(){
atomicInteger.getAndIncrement(); //每次加1-保证原子性的加1
/**
* Atomically increments by one the current value.
*原子性增加1
* @return the previous value
*/
/*public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}*/

volatile int a; //全局变量的默认为0
public void addPlusPlus(){
this.a++;
}
//解决的是volatile不保证原子性的AtomicInteger
//AtomicInteger是 java.util.concurrent.atomic原子包写的类
AtomicInteger atomicInteger=new AtomicInteger();
public void addMyatomic(){
atomicInteger.getAndIncrement(); //每次加1-保证原子性的加1
/**
* Atomically increments by one the current value.
*原子性增加1
* @return the previous value
*/
/*public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}*/
//volatile 不保证原子性的小李子
public static void main(String[] args) {
//1.创建资源类的对象
VolatileTest2 volatileTest2=new VolatileTest2();
//2.创建线程-开始循环-
for(int i=1;i<=30;i++) {
new Thread(()->{
for (int j = 0; j <100 ; j++) {
volatileTest2.addPlusPlus();
volatileTest2.addMyatomic();
}
},String.valueOf(i)).start();
}
//3.main线程是在a++之中有感知的,
System.out.println(Thread.currentThread().getName()+"addPluePlus"+":"+volatileTest2.a);
//得出加过后的最后的值atomiceInteger
System.out.println(Thread.currentThread().getName()+"atomicInteger"+":"+volatileTest2.atomicInteger);
/* mainaddPluePlus:2797
mainatomicInteger:3000
*/
//底层就是CAS的; atomicInteger.getAndIncrement()
}
三、禁止指令重排序(保证有序的执行)


四、面试:在哪些场景下遇见volatile?

单例模式:
class SingletonTest {
//静态的空对象
private static SingletonTest Instance=null;
//2.构造器私有化
private SingletonTest(){
System.out.println("构造器创建一个对象");
}
//静态的公共方法
public static SingletonTest getSingletonTest(){
while (Instance==null){
Instance=new SingletonTest();
}
//返回一个对象
return Instance;
}
}
public class SingletonTest1 {
public static void main(String[] args) {
//单机版的;
System.out.println(SingletonTest.getSingletonTest()==SingletonTest.getSingletonTest());
System.out.println(SingletonTest.getSingletonTest()==SingletonTest.getSingletonTest());
System.out.println(SingletonTest.getSingletonTest()==SingletonTest.getSingletonTest());
System.out.println(SingletonTest.getSingletonTest()==SingletonTest.getSingletonTest());
//多线程
for(int i=1;i<10;i++) {
new Thread(()->{
SingletonTest.getSingletonTest();
System.out.println(Thread.currentThread().getName()+SingletonTest.getSingletonTest());
},String.valueOf(i)).start();
//构造器莫名其妙的输出了很多次--也即是说一个构造器被执行多次; 多线程环境下不行;
}
}
}

2.单例模式的DCL(double check Lock)双端检锁机制---》可重复锁
public static SingletonTest02 getSingletonTest(){
//2.利用的是dcl的使用同步代码块;
if (Instance==null){
synchronized (SingletonTest02.class){
if (Instance==null){
Instance=new SingletonTest02();
}
}
}
//在加锁前后都要检查
return Instance;
}

DCL---可能不安全.因为存在的是一个指令重排的过程

在单例的这个对象前面加入volatil
//volatile的作用是禁止重排序
private static volatile SingletonTest02 Instance=null;边栏推荐
猜你喜欢

动态规划之0-1背包问题(详解+分析+原码)

The device is in use when win10 ejects USB

BUUCTF(5)

CloudCompare源码分析:读取ply文件
Gcache of goframe memory cache

Huawei equipment configuration hovpn

【解决】修改子物体Transform信息导致变换不对称、异常问题的解决方案

SVN本地部署server和cleint 并用阿里云盘自动备份

leetcode 257. Binary Tree Paths 二叉树的所有路径(简单)

Study notes of mattlotlib and Tkinter (I)
随机推荐
Lecture de l'article dense Visual SLAM for RGB - D Cameras
Learn to crawl for a month and earn 6000 a month? Don't be fooled. The teacher told you the truth about the reptile
Simple example of logistic regression for machine learning
还在直接用 localStorage 么?该提升下逼格了
移动端——swipe特效之图片时间轴
消息队列入门MQ
习题8-8 判断回文字符串 (20 分)
Svn deploys servers and cleints locally and uses alicloud disks for automatic backup
华为设备配置HoVPN
STM32 Development Notes 112:ads1258 driver design - read register
习题9-1 时间换算 (15 分)
Exercise 11-3 calculate the longest string length (15 points)
Matlab point cloud processing (XXV): point cloud generation DEM (pc2dem)
IEEE-754 浮点转换器
Brief introduction to integrity
习题8-5 使用函数实现字符串部分复制 (20 分)
启牛推荐开通的证券账户安全吗?靠谱吗
Tkinter学习笔记(三)
图书管理系统
重温c语言一