栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java共享内存模型下并发编程问题与分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java共享内存模型下并发编程问题与分析

系列文章:【并发编程】知识脉络

前言

        上一篇文章了解了JMM:JMM是什么?_披甲上战场的博客-CSDN博客

        文末提出了这种共享内存的工作模式有哪些隐患,这篇文章来分析。

核心问题
  • 可见性:如何保证某个线程的共享变量副本变化后其他线程可见?
  • 有序性:如何保证共享变量副本的读写主内存按顺序执行?
  • 原子性:如何保证某个线程的读写主内存完整执行?
更核心的问题是三种问题未必单独出现!(混合味果汁) 官网案例
  • Chapter 8. Classes案例地址 Chapter 8. Classes 
  • 案例介绍:
class Test {
    static int i = 0, j = 0;
    static void one() { i++; j++; }
    static void two() {
        System.out.println("i=" + i + " j=" + j);
    }
}

使用方法:一个线程重复调用one(),另一个线程重复调用two()。

隐患现象:two()偶尔会输出一个大于i值的j值。

问题原因:因为示例中没有同步,i和j的共享值可能会被打乱顺序更新。

原因解释:

  •  解决方案(一):同步方法Synchronized修饰方法
class Test {
    static int i = 0, j = 0;
    static synchronized void one() { i++; j++; }
    static synchronized void two() {
        System.out.println("i=" + i + " j=" + j);
    }
}

使用方法:在方法上用Synchronized修饰。

解决问题:

  • 这可以防止one()和two()并发执行。
  • 可以确保i和j的共享值在方法1返回之前都被更新。

图例解释:

 

  • 解决方案(二):变量用volatile修饰
class Test {
    static volatile int i = 0, j = 0;
    static void one() { i++; j++; }
    static void two() {
        System.out.println("i=" + i + " j=" + j);
    }
}

使用方法:变量i和j用关键字volatile修饰

解决问题:

  • 这允许one()和two()并发执行。
  • 保证对i和j的共享值的访问发生的次数和顺序与每个线程在执行程序文本时发生的次数完全相同。

图例解释:

总结 1、能保证可见性的举手‍♂️?
  • volatile、synchronized、内存屏障、Lock、final举手了。
2、能保证有序性请举手‍♂️?
  • volatile、synchronized、Lock举手了。
3、能保证原子性的举手‍♂️?
  • synchronized、Lock、CAS举手了。
结束语

        之后我们逐一拜访一下这些举手‍♂️的......

    

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/356456.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号