当前位置: 首页 > wzjs >正文

做公司网站多少钱百度链接

做公司网站多少钱,百度链接,网站移动端是什么问题吗,山东济宁做网站的公司volatile 是Java中一个用于解决多线程内存可见性和禁止指令重排序问题的关键字,下面从多个方面深入且易懂地解析它与JVM的关系。 1. 内存可见性 问题背景:在多线程环境下,每个线程都有自己的工作内存,线程对变量的操作&#xff…

volatile 是Java中一个用于解决多线程内存可见性和禁止指令重排序问题的关键字,下面从多个方面深入且易懂地解析它与JVM的关系。

1. 内存可见性

  • 问题背景:在多线程环境下,每个线程都有自己的工作内存,线程对变量的操作(读取、修改)都在工作内存中进行,而不是直接操作主内存中的变量。这就可能导致一个线程对变量的修改,其他线程不能及时看到。例如:
public class VisibilityProblem {private static boolean flag = false;public static void main(String[] args) {new Thread(() -> {while (!flag) {// 线程1在等待flag变为true}System.out.println("线程1结束等待");}).start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {flag = true;System.out.println("线程2修改了flag");}).start();}
}

在上述代码中,线程2修改了 flag 变量,但线程1可能一直无法感知到这个变化,导致线程1无限循环。

  • volatile 的作用:当一个变量被声明为 volatile 时,线程对该变量的修改会立即同步到主内存,并且其他线程在读取该变量时,会强制从主内存中获取最新值,而不是使用自己工作内存中的缓存值。修改上述代码如下:
public class VolatileVisibility {private static volatile boolean flag = false;public static void main(String[] args) {new Thread(() -> {while (!flag) {// 线程1在等待flag变为true}System.out.println("线程1结束等待");}).start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {flag = true;System.out.println("线程2修改了flag");}).start();}
}

此时,线程2修改 flag 后,线程1能及时获取到新值,从而结束循环。

2. 禁止指令重排序

  • 指令重排序概念:为了提高程序执行效率,JVM和处理器会对指令进行优化,其中一种优化方式就是指令重排序。在单线程环境下,指令重排序不会影响最终执行结果,但在多线程环境下可能会导致问题。例如:
public class ReorderingProblem {private static int a = 0;private static int b = 0;public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {a = 1; // 语句1b = 2; // 语句2});Thread thread2 = new Thread(() -> {if (b == 2) { // 语句3System.out.println(a); // 语句4}});thread1.start();thread2.start();thread1.join();thread2.join();}
}

在理想情况下,线程1先执行完 a = 1b = 2,线程2执行时 b == 2 为真,会输出 1。但由于指令重排序,线程1可能先执行 b = 2,然后执行 a = 1,此时线程2执行时 b == 2 为真,但 a 可能还未被赋值为 1,输出结果可能为 0

  • volatile 对指令重排序的限制volatile 关键字具有禁止指令重排序的语义。当一个变量被声明为 volatile 时,在 volatile 变量的写操作之前的所有操作,都先行发生于该 volatile 变量的写操作;而 volatile 变量的读操作,先行发生于在其之后的所有操作。这确保了 volatile 变量相关的操作顺序与代码顺序一致。例如:
public class VolatileReordering {private static volatile int a = 0;private static int b = 0;public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {a = 1; // 语句1b = 2; // 语句2});Thread thread2 = new Thread(() -> {if (b == 2) { // 语句3System.out.println(a); // 语句4}});thread1.start();thread2.start();thread1.join();thread2.join();}
}

这里 a 被声明为 volatile,保证了语句1在语句2之前执行,并且语句1的结果对线程2可见,从而避免了指令重排序带来的问题。

3. volatile 与JVM内存模型

JVM内存模型定义了主内存和工作内存之间的交互关系,volatile 关键字正是基于这个模型来实现其功能的。

  • volatile 写操作:当一个线程对 volatile 变量进行写操作时,JVM会将该变量在工作内存中的最新值刷新到主内存中,同时会确保在这个写操作之前的所有普通写操作都已经刷新到主内存。
  • volatile 读操作:当一个线程对 volatile 变量进行读操作时,JVM会强制从主内存中读取该变量的值,而不是使用工作内存中的缓存值,并且会确保在这个读操作之后的所有普通读操作都能看到 volatile 变量的最新值。

4. volatile 的使用场景

  • 状态标记:常用于标记某些状态,例如线程的运行状态。如一个线程负责数据加载,另一个线程负责数据处理,数据加载线程完成加载后通过修改 volatile 标记通知处理线程。
public class DataLoader {private static volatile boolean dataLoaded = false;public static void main(String[] args) {new Thread(() -> {// 模拟数据加载try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}dataLoaded = true;}).start();new Thread(() -> {while (!dataLoaded) {// 等待数据加载完成}System.out.println("开始处理数据");}).start();}
}
  • 单例模式中的双重检查锁定(DCL):在实现单例模式时,使用 volatile 可以防止指令重排序导致的对象初始化问题。
public class Singleton {private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

5. volatile 的局限性

  • 不保证原子性volatile 不能保证复合操作的原子性。例如 count++ 操作,它实际上包含读取、增加和写入三个步骤,即使 count 被声明为 volatile,在多线程环境下仍然可能出现数据竞争问题。对于这种情况,需要使用 AtomicInteger 等原子类或者 synchronized 关键字来保证原子性。
public class VolatileAtomicityProblem {private static volatile int count = 0;public static void main(String[] args) throws InterruptedException {Thread[] threads = new Thread[100];for (int i = 0; i < 100; i++) {threads[i] = new Thread(() -> {for (int j = 0; j < 1000; j++) {count++;}});threads[i].start();}for (Thread thread : threads) {thread.join();}System.out.println("最终count的值: " + count);}
}

上述代码中,由于 count++ 不是原子操作,最终输出的 count 值往往小于预期的 100000

综上所述,volatile 关键字在多线程编程中是一个强大的工具,能够有效解决内存可见性和指令重排序问题,但需要清楚其适用场景和局限性,以确保多线程程序的正确性。

http://www.dtcms.com/wzjs/187531.html

相关文章:

  • 网站首页网址互联网优化
  • 想做网站怎么跟做网站的公司谈判网站如何seo推广
  • 东莞网站排名优化价格百度直播
  • 苏州seo网站优化软件怎么做信息流广告代理商
  • 海丰县网站设计百度竞价排名商业模式
  • 网站打不开是为什么seo国外英文论坛
  • 如何申请域名建网站抖音seo供应商
  • vs2010网站开发 调试 打不开页面 浏览器错误上海sem
  • 网站上的按钮怎么做qq群推广方法
  • 介绍自己做衣服的网站中国站长之家官网
  • wordpress 评分插件济南seo优化
  • 西部数据网站管理助手免费一键搭建网站
  • 一般做企业网站多少钱什么叫营销
  • 黑龙江网站建设郑州seo学校
  • 实战营销型网站建设百度指数分析官网
  • 网站培训费用广州seo推广营销
  • 怎么做网站引流搜索量查询
  • 云浮哪有公司做网站的推广策略及推广方式
  • 手机端网站用dw怎么做专业seo网络营销公司
  • 做网络投票网站好做吗情感网站seo
  • 滁州网络推广公司河南网站优化排名
  • 微信小程序推广软件百度如何优化排名靠前
  • 已经备案的网站新增ip怎么做怎么在百度免费推广
  • 重庆网站建设找重庆万为网站流量
  • ecs搭建wordpress站点武汉排名seo公司
  • 营销型企业网站建设的基本原则是怎么在腾讯地图上添加自己的店铺
  • 企业怎么搭建网站推广团队在哪里找
  • 这是为了使网页seo建设者
  • 网站设计实训心得旺道seo软件技术
  • 建筑模板是干嘛用的seo领导屋