范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

关于JAVA中volatile使用的一些笔记

  写在前面我的需求:问答  看到一个小伙伴问了这样JAVA并发的问题,然后我做了解答,主要使用了volatile
  (1)某电影放映厅一共有10排,每排10个座位,座位号为"排号+列号",如第8排,座位号是8A-8J;
  (2)此放映厅某一场次现有100张票要卖出,观众可以通过四个渠道购票:电影院、时光网、美团和支付宝;
  (3)各个售票点的效率不同,每卖出一张票,各个售票点所需要的时间分别为:电影院3秒,时光网5秒,美团2秒,支付宝6秒;
  现在这4个售票点同时售票,根据以上信息,用多线程模拟这4个售票点的售票情况。要求打印出每个售票点所卖出电影票的座位号,座位号随机确定。  我需要解决的问题:答完之后他反馈有问题,我测了几次,发现确实有问题。会有打印重票的时候,对于 volatile  的理解有些问题我是这样做的:微信群里问了大佬。使用了原子类(atomic)解决这个问题。 这里对volatile总结一下,当然没有涉及啥底层的东西,很浅。
  太敏感的人会体谅到他人的痛苦,自然就无法轻易做到坦率。所谓的坦率,其实就是暴力。-----太宰治《候鸟》
  我们先来看看他这到题,座位号随机确定我们直接用数子自增模拟,没有实现,想实现的话,可以把所有的号码随机初始化一个Set,然后每次pull一个出来。
  下面是我最开始的解决方案,使用 volatile  来处理线程安全问题,认为我每次都可以拿到最新的,即可以满足线程安全。但是打印出来的数据有重复的,忽略了volatile修饰变量不满足原子性的问题,而 index++  本身也不是原子操作,所以会有重票的问题 import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit;   /**  * @Classname Ticket  * @Description TODO  * @Date 2021/12/8 19:00  * @Created LiRuilong  */ public class Ticket implements Runnable {     //最多受理100笔业务     private static final int MAX = 100;     // 开始业务     //static AtomicInteger index = new AtomicInteger(0);     private static   volatile int index = 0;     // 电影院3秒,时光网5秒,美团2秒,支付宝6秒;     private static volatile Map map = new HashMap() {{         put("电影院", new ArrayList<>());         put("时光网", new ArrayList<>());         put("美团", new ArrayList<>());         put("支付宝", new ArrayList<>());     }};      @Override     public void run() {         while (index < MAX) {             try {                 String currentThreadName = Thread.currentThread().getName();                 switch (currentThreadName) {                     case "电影院": {                         map.get("电影院").add(++index);                         TimeUnit.MILLISECONDS.sleep(3);                     }                     break;                     case "时光网": {                         map.get("时光网").add(++index);                         TimeUnit.MILLISECONDS.sleep(5);                     }                     break;                     case "美团": {                         map.get("美团").add(++index);                         TimeUnit.MILLISECONDS.sleep(2);                     }                     break;                     case "支付宝": {                         map.get("支付宝").add(++index);                         TimeUnit.MILLISECONDS.sleep(6);                     }                     break;                     default:                         break;                 }             } catch (Exception e) {                 e.printStackTrace();             }         }     }      public static void main(String[] args) {          final Ticket task = new Ticket();         //电影院3秒,时光网5秒,美团2秒,支付宝6秒;         new Thread(task, "电影院").start();         new Thread(task, "时光网").start();         new Thread(task, "美团").start();         new Thread(task, "支付宝").start();          Runtime.getRuntime().addShutdownHook(new Thread() {             @Override             public void run() {                 map.forEach((o1, o2) -> {                     System.out.println(o1 + " | 总票数:"+o2.size()+o2.stream().reduce(":", (a, b) -> a + " " + b));                 });             }         });     } }  ========================== 支付宝 | 总票数:18: 2 8 13 18 24 30 36 41 47 53 58 64 69 77 82 87 94 100 电影院 | 总票数:32: 3 4 7 10 12 16 19 23 25 27 32 35 37 40 43 46 49 52 56 58 62 65 68 73 76 80 83 86 89 92 95 98 时光网 | 总票数:20: 1 5 10 14 20 24 28 34 38 44 48 54 59 64 71 75 81 85 91 97 美团 | 总票数:43: 2 4 6 9 11 12 15 17 21 22 24 26 29 31 33 36 37 39 42 45 47 50 51 55 57 60 61 63 66 67 70 72 74 78 79 82 84 86 88 90 93 96 99
  后来通过使用原子类,使用了AtomicInteger来满足 index++  的原子性,票数可以正常的打印出来。package com.ztesoft.pwd.bo;  import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger;  /**  * @Classname Ticket  * @Description TODO  * @Date 2021/12/8 19:00  * @Created LiRuilong  */ public class Ticket implements Runnable {     //最多受理100笔业务     private static final int MAX = 100;     // 开始业务     static AtomicInteger index = new AtomicInteger(0);     //private static   volatile int index = 0;     // 电影院3秒,时光网5秒,美团2秒,支付宝6秒;     private static volatile Map map = new HashMap() {{         put("电影院", new ArrayList<>());         put("时光网", new ArrayList<>());         put("美团", new ArrayList<>());         put("支付宝", new ArrayList<>());     }};      @Override     public void run() {         while (index.get() < MAX) {             try {                 String currentThreadName = Thread.currentThread().getName();                 switch (currentThreadName) {                     case "电影院": {                         map.get("电影院").add(index.addAndGet(1));                         TimeUnit.MILLISECONDS.sleep(3);                     }                     break;                     case "时光网": {                         map.get("时光网").add(index.addAndGet(1));                         TimeUnit.MILLISECONDS.sleep(5);                     }                     break;                     case "美团": {                         map.get("美团").add(index.addAndGet(1));                         TimeUnit.MILLISECONDS.sleep(2);                     }                     break;                     case "支付宝": {                         map.get("支付宝").add(index.addAndGet(1));                         TimeUnit.MILLISECONDS.sleep(6);                     }                     break;                     default:                         break;                 }             } catch (Exception e) {                 e.printStackTrace();             }         }     }      public static void main(String[] args) {          final Ticket task = new Ticket();         //电影院3秒,时光网5秒,美团2秒,支付宝6秒;         new Thread(task, "电影院").start();         new Thread(task, "时光网").start();         new Thread(task, "美团").start();         new Thread(task, "支付宝").start();          Runtime.getRuntime().addShutdownHook(new Thread() {             @Override             public void run() {                 map.forEach((o1, o2) -> {                     System.out.println(o1 + " | 总票数:"+o2.size()+o2.stream().reduce(":", (a, b) -> a + " " + b));                 });             }         });     } }  ================================= 支付宝 | 总票数:16: 4 10 16 22 29 36 41 47 55 61 68 73 80 87 93 99 电影院 | 总票数:27: 2 6 9 13 17 21 24 27 32 34 39 42 46 49 52 57 59 64 67 71 75 77 82 86 90 92 97 时光网 | 总票数:17: 3 8 14 19 26 30 37 44 48 54 60 65 72 78 84 89 96 美团 | 总票数:40: 1 5 7 11 12 15 18 20 23 25 28 31 33 35 38 40 43 45 50 51 53 56 58 62 63 66 69 70 74 76 79 81 83 85 88 91 94 95 98 100  关于volatile的使用
  被volatile关键字修饰的实例变量或者类变量具备两层语义: 保证了不同线程之间对共享变量的可见性, 禁止对volatile变量进行重排序。
  每个线程都运行在栈内存中,每个线程都有自己的工作内存(Working Memory),比如寄存器Register,高速缓存存储器Cache等,线程的计算一般是通过工作内存进行交互的,线程在初始化时从主内存中加载所需要的变量值到工作内存中,然后在线程运行时,如果读取内存,则直接从工作内存中读取,若是写入则先写入到工作内存中,之后在刷新到主内存中。
  在多线程情况下,可能读到的不是最新的值,可以使用 synchronized  同步代码块,或使用Lock  锁来解决该问题。JAVA  可以使用volatile  解决,在变量前加volatile  关键字,可以保证每个线程对本地变量的访问和修改都是直接与主内存交互的,而不是与本线程的工作内存交互  。
  但是Volatile关键字并不能保证线程安全,换句话讲它只能保证当前线程需要该变量的值能够获得最新的值,而不能保证多个线程修改的安全性。
  使用  volatile  ,需要保证:对变量的写操作不依赖于当前值; 该变量没有包含在具有其他变量的不变式中关于volatile的一些基本概念
  volatile关键字只能修饰类变量和实例变量,对于方法参数,局部变量已及实例常量,类常量都不能进行修饰。 原子性,有序性和可见性
  并发编程的三个重要的特性
  可见性
  有序性
  原子性
  当一个线程对共享变量进行了修改,那么另一个变量可以立即看到。 volatile  具有保证可见性的语义
  Java在运行期会对代码进行优化,执行顺序未必就是编译顺序,  volatile  具有保证有序性的语义。
  多个原子性的操作在一起就不再是原子性操作了。
  Java提供了以下三种方式来保证可见性
  Java提供了三种保证有序性的方式,具体如下
  简单的读取与赋值操作是原子性的,将一个变量赋给另外一个变量的操作不是原子性的。
  使用关键字volatile,当一个变量被volatile关键字修饰时,对于共享资源的读操作会直接在主内存中进行(当然也会缓存到工作内存中,当其他线程对该共享资源进行了修改,则会导致当前线程在工作内存中的共享资源失效,所以必须从主内存中再次获取),对于共享资源的写操作当然是先要修改工作内存,但是修改结束后会立刻将其刷新到主内存中。
  通synchronized 关键字实现,同步块保证任何时候只有一个线程获得锁,然后执行同步方法,并且还会确保在锁释放之前,会将对变量的修改刷新到主内存当中
  通过JUC提供的显式锁Lock也能够保证可见性, Lock的lock方法能够保证在同一时刻只有一个线程获得锁然后执行同步方法,并且会确保在锁释放(Lock的unlock方法)之前会将对变量的修改刷新到主内存当中。
  使用 volatile  关键字来保证有序性。使用synchronized  关键字来保证有序性。使用显式锁Lock  来保证有序性。
  Java内存模型(JMM)只保证了基本读取和赋值的原子性操作,其他的均不保证,如果想要使得某些代码片段具备原子性,需要使用关键字 synchronized  ,或者JUC  中的lock  。如果想要使得int等类型自增操作具备原子性,可以使用JUC包  下的原子封装类型java.util.concurrent.atomic.*  volatile和synchronized区别
  区别
  描述
  使用上区别
  volatile关键字只能用来修饰实例变量或者类变量,不能修饰方法已及方法参数和局部变量和常量。
  synchronized关键字不能用来修饰变量,只能用于修饰方法和语句块。
  volatile修饰的变量可以为空,同步块的monitor不能为空。
  对原子性的保证
  volatile无法保证原子性
  synchronizde能够保证。因为无法被中途打断。
  对可见性的保证
  都可以实现共享资源的可见性,但是实现的机制不同
  synchronized借助于JVM指令monitor enter 和monitor exit ,通过排他的机制使线程串行通过同步块,在monitor退出后所共享的内存会被刷新到主内存中。
  volatile使用机器指令(硬编码)的方式, lock  迫使其他线程工作内存中的数据失效,不得不主内存继续加载。
  对有序性的保证
  volatile关键字禁止JVM编译器已及处理器对其进行重排序,能够保证有序性。
  synchronized保证顺序性是串行化的结果,但同步块里的语句是会发生指令从排。
  其他
  volatile不会使线程陷入阻塞
  synchronized会会使线程进入阻塞。

苹果XR,搭载A12处理器,当主力机也没问题2021生机大会说句实话,买这款手机就是买他的A12处理器,至于其他的配置其实也够用,这款手机和XS的最大区别就是一个是单摄,一个是双摄,而且屏幕也是XS的要好一些。还是那句话,买索尼WHXB910N头戴式无线降噪耳机开售售价1299元昨日,索尼WHXB910N头戴式无线降噪耳机正式开售,售价为1299元。据官方介绍,索尼WHXB910N耳机采用与WH1000XM4相同的双反馈麦克风,可灵敏地捕捉环境噪音。通过S曝三星Exynos2200GPU性能对比骁龙8处理器没有优势今天,博主i冰宇宙在社交平台爆料,三星即将发布的旗舰处理器Exynos2200芯片对比高通骁龙8依旧没有优势。i冰宇宙指出,原以为AMDGPU加持的Exynos2200芯片会让三星有哪些英语口语好的APP,海豚班AI了解一下一英语流利说是一款智能口语打分软件,应用于PC端或者手机端,内置各种口语练习场景,用户可以进行跟读模仿等练习,软件会根据自己发音匹配程度予以打分。另外还有各种学习圈子,在这里聚集着传三星微软合作AR项目产品预计2024年亮相韩国媒体TheElec近日报道称,三星电子已与微软合作启动一个基于HoloLens的AR项目。消息人士向TheElec透露三星于今年3月成立了负责该项目的工作组,这一项目于今年夏天iPhoneSE3价格曝光,还会有大屏幕版iPhoneSE苹果将会在明年的时候推出新款5G版iPhone手机iPhone14系列手机,目前关于iPhone14系列手机的爆料信息已经越来越多,根据爆料显示iPhone14系列手机有四款不同的vivo荣获最佳技术创新奖,它的杀手锏是什么?在竞争日益激烈的智能手机市场,为了满足消费者日益变化的用机需求,各大手机品牌围绕产品和技术层面不断创新,新品手机陆续面世,技术也在不断革新和优化,用一句你方唱罢我登台来形容再合适不如果联想当年选择倪光南,今天会怎样?历史没有如果。并且在当时的历史条件下中国科学院选择柳传志是不错的抉择。柳传志的问题在于联想改制之后其个人私欲无限膨胀,将国家和人民抛在脑后,导致联想出现现在的状况,这与一个共产党员互联网大裁员开始了,各位老铁们,Areyouready?前些年年年都在炒,互联网人工资有多高。最近几年发现炒作互联网人的工资没流量了,为啥呢,炒应届生工资高,可人均985211硕博的门槛太高,引不起共鸣炒老员工百万年薪,那更不行,门槛更现在买骁龙870,8256的手机还能用五年吗?保护得当五年后肯定能用的,聊聊微信玩玩小游戏不在话下,五年的变化太大了说不定你就发了呢,到时你就不是玩手机了是玩车和表微笑骁龙870和上一代骁龙旗舰865性能差不多!我们只需要看看英特尔CEO供应链问题将持续至2023年华尔街日报12月8日消息,英特尔和埃森哲CEO周二在华尔街日报举办的CEO理事会峰会上表示,对一些公司来说,波及整个美国经济的供应链问题正在改善,但长期修复可能需要更多时间。网上零
C语言项目实战气球射击游戏项目!200行代码轻松实现这篇文章主要为大家详细介绍了C语言实现气球射击小游戏,示例源码介绍的非常详细,具有相当的参考价值,感兴趣的小伙伴们可以参考一下的!游戏介绍打气球,英文名是BalloonHit。就像高清透雾摄像机的工作原理透雾摄像机的诞生不仅解决了极端天气监控难得问题,同时也为全天候摄像机打开缺口,无论处于何种环境下都能实现全天候高清监控。透雾摄像机中植入的宽动态夜视增强功能,其实夜晚的光照条件远比什么原因使得你还买或者用三星?用过三部三星,到现在还没坏,最老的一个7年了,现在还在用第一个原因三星手机好,做工品质一流都说三星手机贵,这也是不争的事实,但是依旧也是有人买单,别看国内用户少,但是在海外的支持者为什么女孩子都喜欢买iPhone,这四点也许说到了心坎上苹果手机以其强大流畅的性能而闻名,所以一些朋友总是认为它是大多数喜欢玩游戏的男性用户。事实上,大数据调查显示,iphone用户女性占60男性只占40看现在身边拿着i,phone大多拼多多商家有哪些常用套路?如何轻松买到正品?记住这6点随便买文史记新说编辑史记新说拼多多的山寨货有多让人哭笑不得?网友1在拼多多上买个立白洗衣液,收到货一看是立曰洗衣粉网友2我妈在拼多多上拼的安慕希20袋,我妈还以为有袋装的,结果的确是包装电动牙刷哪个牌子好,使用电动牙刷都有哪些好处?随着电动牙刷行业规模逐步扩大,市场上充斥着各种各样的功能型电动牙刷,再加上国人对于口腔健康的意识逐步提高,电动牙刷的使用较之前更为普遍。然而,一部分传统牙刷大军还是坚守阵营,他们认你见过最亮的评论是什么?司马南评联想,他评的是联想高官柳杨,实质也是砰击了中国利益集团和资本家的恶行,司马南的评论代表了全国人民的心声,是几年来最亮的评论!真正的国人都为他点赞赞赞不知道你们看视频的时候,深圳华为旁边的联发天境雅居值得买吗?联发天境此次共备案570套房,住宅525套(12为商业部分,住宅主要分布在356栋),住宅单价5。76。6万平之间。项目主推89平3房112平4房单位,采用精装交付项目邻近地铁10三星ZFold3折叠屏手机推送OneUI4beta更新三星GalaxyZFold3折叠屏手机现已推送OneUI4beta版本更新,大小为2386。17MB。OneUI4(Android12)可为Galaxy设备带来多种新功能和增强功能投融资周报字节参投迪拜电商物流企业威马汽车获1。52亿美元融资(整理胡毓靖)过去一周,互联网大厂中,B站投资游戏研发公司,小米参投手机芯片企业,字节跳动参投迪拜电商物流企业iMile。此外,威马汽车再获1。52亿元D2轮融资。餐饮护肤宠物则是36氪首发车路协同公司艾氪英诺获千万级天使轮融资,为无人配送车提供安全冗余文李安琪编辑苏建勋36氪获悉,苏州艾氪英诺机器人科技有限公司(以下称艾氪英诺)获得千万级天使轮融资,由苏高新创投汇毅资本和成电校友会投资。艾氪英诺成立于2019年,是一家以路侧多源