Java基础知识总结(77)

news/2024/9/22 20:48:33/

 * 2、JMM模型

    JMM(Java Memory Model):Java 内存模型,是 Java 虚拟机规范中所定义的一种内存模型,Java 内存模型是标准化的,屏蔽掉了底层不同计算机的区别。也就是说,JMM 是 JVM 中定义的一种并发编程的底层模型机制。

   

    JMM内存模型规定详解如下:

   

        所有的共享变量都存储于主内存。这里所说的变量指的是实例变量和类变量,不包含局部变量,因为局部变量是线程私有的,因此不存在竞争问题。

            每一个线程还存在自己的工作内存,线程的工作内存,保留了被线程使用的变量的工作副本。

            线程对变量的所有的操作(读,写)都必须在工作内存中完成,而不能直接读写主内存中的变量。

            不同线程之间也不能直接访问对方工作内存中的变量,线程间变量的值的传递需要通过主内存中转来完成。

   

        总结:

   

            1. 每个线程都有自己的私有内存(工作内存)

            2. 线程对共享变量的操作只能在私有内存中进行,操作完成后写入到主内存中

            3. 共享比那里都存储在主内存中。

   

        假设此时内存中现在有两个线程在运行,如果A、B两个线程之间要通信,必须经历以下2个步骤

   

            线程A把本次内存中更新过的共享变量刷新到主内存中去。

            线程B从主内存中读取线程A已经更新过的共享变量。

            然而,JMM 这样的规定可能会导致线程对共享变量的修改没有即时更新到主内存,或者线程没能够及时将共享变量的最新值同步到工作内存中,从而使得线程在使用共享变量的值时,该值并不是最新的。

   

        JMM特性:

   

            1.原子性:

                一个或者多个操作不可分割,要么全部执行,并且执行过程中不会被任何因素打断,要么就都不执行。Java中可以使用synchronized保证原子性。

            2.可见性:

                是指当一个线程修改了某一个共享变量的值时,其他线程是否能够立即知道这个修改。显然,对于串行程序来说,可见性问题是不存在的。因为你在任何一个操作步骤中修改了某个变量,在后续的步骤中读取这个变量的值时,读取的一定是修改后的新值。Java中的volatile、synchronized、Lock都能保证可见性。如一个变量被volatile修饰后,表示当一个线程修改共享变量后,其会立即被更新到主内存中,其他线程读取共享变量时,会直接从主内存中读取。而synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。

            3.有序性:

                对于一个线程的执行代码而言,我们总是习惯性地认为代码是从前往后依次执行的。这么理解也不能说完全错误,因为就一个线程内而言,确实会表现成这样。但是,在并发时,程序的执行可能就会出现乱序。给人的直观感觉就是:写在前面的代码,会在后面执行。听起来有些不可思议,有序性问题的原因是程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致。

                在单核CPU的场景下,当指令被重排序之后,编译器和CPU都需要遵守As-if-Serial规则,无论如何重排序,都必须保证代码在单线程下运行正确

   

    3、synchronized关键字

       

        synchronize是一个修饰符,表示同步的意思,可以修饰方法,也可以修饰代码块。修饰的方法叫做同步方法,修饰的代码块叫做同步代码块,被synchronized修饰的方法或则代码,也叫做临界区,临界区的特点在同一时刻有且只能有一个线程访问。

/**

 * 线程不加锁可能会出现值不同步的情况

   */

   public class SynchronizedDemo {

   //静态成员变量 在主内存中

   static int i;

   //静态成员方法

   public static void add(){

       i++;

   }

   public static void main(String[] args) throws InterruptedException {

       Thread t1 = new Thread(()->{

           for (int j = 0; j < 100; j++) {

               //t1线程调用add方法,先从主内存中复制变量i到本地内存中

               //执行逻辑代码

               //将执行产生的新结果写入到主内存中

               add();

           }

       });

       Thread t2 = new Thread(()->{

           for (int j = 0; j < 100; j++) {

               add();

           }

       });

       //启动t1线程

       t1.start();

       //启动t2线程

       t2.start();

       //休眠main线程,让其他线程优先执行

       TimeUnit.SECONDS.sleep(1);

       //由于线程没有加锁,故线程t1在进行数据的逻辑处理时,由于分配的时间片结束用完,导致线程t1出现死锁的情况,线程t2先执行。会出现值不同步的非线程安全的情况

       System.out.println(i);

   }

   }


http://www.ppmy.cn/news/1442718.html

相关文章

(五)小案例银行家应用程序-实现转账

现在我们想实现用户之间相互转账的功能&#xff1b; ● 和之前一样我们还是要通过这个点击&#xff0c;页面元素一再写在变量里面了 在这里插入图片描述 btnTransfer.addEventListener(click, function (e) {e.preventDefault();const amount Number(inputTransferAmount.val…

python_django农产品物流信息服务系统6m344

Python 中存在众多的 Web 开发框架&#xff1a;Flask、Django、Tornado、Webpy、Web2py、Bottle、Pyramid、Zope2 等。近几年较为流行的&#xff0c;大概也就是 Flask 和 Django 了 Flask 是一个轻量级的 Web 框架&#xff0c;使用 Python 语言编写&#xff0c;较其他同类型框…

民航电子数据库:报错merge sql error, dbType null, druid-1.1.9, sql : xxx

目录 一、场景二、SQL三、报错信息四、排查五、原因六、解决 一、场景 1、对接民航电子数据库 2、limit查询时报错 二、SQL SELECT openid,headimgurl,nickname FROM t_mb_weixinuser WHERE openid? AND vdnId ? LIMIT 1三、报错信息 merge sql error, dbType null, dru…

iOS - Runloop在实际开发中的应用

文章目录 iOS - Runloop在实际开发中的应用1. 控制线程生命周期&#xff08;线程保活&#xff09;2. 解决NSTimer在滑动时停止工作的问题2.1. 案例2.2 解决 3. 监控应用卡顿4. 性能优化 iOS - Runloop在实际开发中的应用 1. 控制线程生命周期&#xff08;线程保活&#xff09;…

MySQL--创建,删除,查找,案例

1.数据库的---创建&#xff0c;删除&#xff0c;查找&#xff0c;案例 create database 数据库名称; # 创建一个数据库&#xff0c;所有参数默认 create database 数据库名称 [default chasetutf8mb4] # 创建的同时指定了编码2.drop删除 drop database 数据库名称;3.进入数据库…

ubuntu22.04安装TensorRT(过程记录)

重要说明&#xff1a;此贴经过多次修改。第一次安装的的为trt8.6.1版本。第二次安装的10.0.0.6版本。有些地方可能没改过来&#xff0c;比如链接向导&#xff0c;我懒得改了&#xff0c;但是流程是对的。 cuda和cudnn版本对应关系 tensorRT历史发行版本 CUDA历史发行版本 cudn…

MySql 查询优化

MySQL查询优化涉及多个方面&#xff0c;包括索引优化、查询优化、服务器配置优化等。以下是一些基本的查询优化技巧&#xff1a; 1.使用索引 确保你的查询利用了适当的索引。 SELECT * FROM table_name WHERE column_name value; 2.避免SELECT * 只选择需要的列&#xff…

STM32与OLED显示屏通信(四针脚和七阵脚)

系列文章目录 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. 单片机调试 2. OLED简介 3. 接线 4. OLED驱动函数 4.1 四针脚版本 OLED.c OLED.h OLED_Font.h 4.2 七针脚版本 引脚连接 OLED.c OLED.h OLED_Font.h 5. 主函数 工程文件模板 1. 单片机…