Java基础知识总结(78)

/**

 * 线程加锁

   */

   public class SynchronizedDemo2 {

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

   static int i;

   //静态成员方法

   public static void add(){

       synchronized (SynchronizedDemo2.class){

           i++;

       }

   }

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

       Thread t1 = new Thread(()->{

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

               add();

           }

       });

       Thread t2 = new Thread(()->{

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

               add();

           }

       });

       //启动t1线程

       t1.start();

       //启动t2线程

       t2.start();

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

       TimeUnit.SECONDS.sleep(1);

       //加锁后 不会出现值不同步的情况 每次运行结果都是200

       System.out.println(i);

   }

   }

   加锁后以上程序可能出现的执行过程

               t1线程                              t2线程

   时刻1  抢锁且成功                                    为就绪态

   时刻2   从主内存中复制共享变量到t1线程的私有内存中      为就绪态

   时刻3   对私有内存中的变量进行逻辑处理                     为就绪态

   时刻4   时间片到                                         运行状态

   时刻5    就绪状态                                       抢时间片,但是没有抢到,该线程处于阻塞状态, 直到时间片结束

   时刻6  时间片到,运行状态,将处理后的结果写入主内存中      就绪

   时刻7    退出临界区,释放锁                              抢时间片,并且抢到时间片,开始执行

/**

 * 如果多个线程分别持有自己的锁,则加锁没有意义

 * 锁应是唯一的,体现互斥性

   */

   public class SynchronizedDemo3 {

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

   static int i;

   //静态成员方法

   public static void add(){

       i++;

   }

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

       //注意,锁可以是任意对象

       //定义两个锁

       Object lock1 = new Object();

       Object lock2 = new Object();

       Thread t1 = new Thread(()->{

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

               synchronized(lock1){

                   //为某个具体操作加锁 而不是所有代码

                   add();

               }

           }

       });

       Thread t2 = new Thread(()->{

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

               synchronized(lock2){

                   add();

               }

           }

       });

       //启动t1线程

       t1.start();

       //启动t2线程

       t2.start();

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

       TimeUnit.SECONDS.sleep(1);

       System.out.println(i);

   }

   }


 

/**

 * 证明线程处于休眠状态时,不会释放锁。

   */

   public class SynchronizedDemo4 {

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

       //注意,锁可以是任意对象

       Object lock = new Object();

       Thread t1 = new Thread(()->{

           synchronized(lock){

               System.out.println("t1线程获得锁");

               try {

                   System.out.println("t1线程开始休眠");

                   TimeUnit.SECONDS.sleep(10);

                   System.out.println("t1线程结束休眠");

               } catch (InterruptedException e) {

                   throw new RuntimeException(e);

               }

           }

       });

       Thread t2 = new Thread(()->{

           synchronized(lock){

               Thread thread = Thread.currentThread();

               System.out.println("线程t2获得锁");

               for (int i = 0; i < 50; i++) {

                   //执行t2线程的条件是 线程2抢占锁成功 并且分配到时间片

                   //若在t1线程休眠过程中 t2线程执行该语句 则说明线程在休眠过程中会释放锁,反之则不会

                   System.out.println(thread.getName()+"**********"+i);

               }

           }

           System.out.println("线程t2释放锁");

       });

       //启动t1线程

       t1.start();

       TimeUnit.SECONDS.sleep(1);

       //启动t2线程

       t2.start();

       //休眠main线程

       TimeUnit.SECONDS.sleep(3);

       //获取t2的状态

       System.out.println(t2.getState());//block

       //结论:线程在休眠过程中不会释放锁

   }

   }


 

        synchronized修饰类方法时,锁时当前类对象即类名.class,当synchronized修饰实例方法时,锁时当前对象即this。

/**

 * synchronized修饰类方法 当前类对象作为锁

   */

   public class SynchronizedDemo5 {

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

   static int i;

   //静态成员方法

   public synchronized static void add(){

       i++;

   }

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

       Thread t1 = new Thread(()->{

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

               add();

           }

       });

       Thread t2 = new Thread(()->{

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

               add();

           }

       });

       //启动t1线程

       t1.start();

       //启动t2线程

       t2.start();

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

       TimeUnit.SECONDS.sleep(1);

       System.out.println(i);

   }

   }

/**

 * synchronized修饰实例方法 线程对应的对象作为锁对象

 * 不存在锁竞争,因此在临界区也不会存在互斥性

   */

   public class SynchronizedDemo6 {

   static int i = 0;

   public static void add(){

       i++;

   }

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

       Thread t1 = new Thread(new Runnable() {

           @Override

           public synchronized void run() {

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

                   add();

               }

           }

       }

       );

       Thread t2 = new Thread(new Runnable() {

           @Override

           public synchronized void run() {

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

                   add();

               }

           }

       }

       );

       //启动t1线程

       t1.start();

       //启动t2线程

       t2.start();

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

       TimeUnit.SECONDS.sleep(1);

       System.out.println(i);

   }

   }


 

        synchronized实现原理

   

            monitorenter指令时会尝试获取相应对象的monitor,获取规则如下:

   

                如果monitor的进入数为0,则该线程可以进入monitor,并将monitor进入数设置为1,该线程即为monitor的拥有者。

                如果当前线程已经拥有该monitor,只是重新进入,则进入monitor的进入数加1,所以synchronized关键字实现的锁是可重入的锁。

                如果monitor已被其他线程拥有,则当前线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor。

   

            monitorexit:

   

                只有拥有相应对象的monitor的线程才能执行monitorexit指令。每执行一次该指令monitor进入数减1,当进入数为0时当前线程释放monitor,此时其他阻塞的线程将可以尝试获取该monitor。

   

        synchronized的内存语义

   

            1. 进入synchronized块的内存语义是把在synchronized块内使用到的变量从线程的工作内存中清除,这样在synchronized块内使用到该变量时就不会从线程的工作内存中获取,而是直接从主内存中获取。

            2. 退出synchronized块的内存语义是把在synchronized块内对共享变量的修改刷新到主内存。


 

2、今天没学会什么

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/581146.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UDP和TCP(传输层)

这里写目录标题 UDPUDP的基本特点UDP协议报文格式 TCPTCP协议报文格式TCP特点可靠传输实现机制确认应答超时重传数据丢了应答报文丢了 小结 UDP UDP的基本特点 无连接不可靠传输面向数据报全双工 UDP协议报文格式 2个字节有效范围(无符号): 0 ~ 65535(2^16 - 1). 2个字节有效范…

用数据检验函数正确性,matlab2C

数据存取格式 filename1 g.txt; fid1 fopen(filename1,w); for i 1 : length(g)for j1:size(g,2)if(j1)fprintf(fid1,{%.16f,,g(i,j)); elseif(j>1&&j<151)fprintf(fid1,%.16f,,g(i,j)); elsefprintf(fid1,%.16f},\n,g(i,j));endend%fprintf(fid1,\n…

如何用Python语言实现远程控制4路控制器/断路器

如何用Python语言实现远程控制4路控制器/断路器呢&#xff1f; 本文描述了使用Python语言调用HTTP接口&#xff0c;实现控制4路控制器/断路器&#xff0c;支持4路输出&#xff0c;均可独立控制&#xff0c;可接入各种电器。 可选用产品&#xff1a;可根据实际场景需求&#xf…

Spring Web MVC入门(3)——响应

目录 一、返回静态页面 RestController 和 Controller之间的关联和区别 二、返回数据ResponseBody ResponseBody作用在类和方法的情况 三、返回HTML代码片段 响应中的Content-Type常见的取值&#xff1a; 四、返回JSON 五、设置状态码 六、设置Header 1、设置Content…

2024李卜常识开天斧

2024年&#xff0c;李卜常识开天斧课程以其独特的魅力吸引了众多学子。这门课程如同开天辟地的神斧&#xff0c;帮助我们打开常识知识的大门&#xff0c;引领我们走进一个全新的学习世界。在李卜老师的悉心指导下&#xff0c;我们逐渐掌握了各种常识知识&#xff0c;拓宽了视野…

leaftjs+turfjs+idw纯前端实现等值面绘图+九段线

最近有个绘制等值面图的需求。我们一般的实现路径是&#xff1a; 1.后台绘图&#xff0c;用surfer绘制好&#xff0c;给前端调用叠加到地图。 2.后台用python绘图&#xff0c;绘制好给前端调用&#xff0c;叠加到地图。 3.后台进行插值计算、地图裁剪、最终生成geojson文件或…

VS2019配合QT5.9开发IRayAT430相机SDK

环境配置 VS2019 QT5.9 编译器版本 MSVC2017_64添加系统环境变量&#xff08;完毕后重启电脑&#xff09; 从VS2019中下载Qt插件 从VS2019中添加单个编译组件 上述操作完成后用VS打开工程文件&#xff0c;工程文件地址 &#xff1a; C:\Users\86173\Desktop\IRCNETSDK_W…

初识 Linux

一、基础命令 0、 ls cd cat pwd 当前工作目录 find -name 测试.py 查找文件 grep "学院" 测试.py 查找字符串 "学院" 在文件 测试.py 中位置&#xff0c;输出所在的 行 1、重定向器 echo "Hello Kali Linux!" > Hello 创建 文件 Hel…

openssl3.2 - exp - 使用默认的函数宏,在release版中也会引入__FILE__

文章目录 openssl3.2 - exp - 使用默认的函数宏&#xff0c;在release版中也会引入__FILE__概述笔记验证是否__FILE__在release版下也能用&#xff1f;将openssl编译成release版的&#xff0c;看看CRYPTO_free()是否只需要一个参数就行&#xff1f;将工程中的openssl相关的库换…

stream中的foreach,allMatch,noneMatch,anyMatch的基本使用

1.1foreach遍历集合元素 1.2anyMatch()的使用 结论:上边使用foreach循环遍历和使用anyMatch()的作用相同 2.allMatch() 2.1初级使用 2.2进级使用 3.noneMatch()使用

Python 实现视频去抖动技术

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 视频去抖动是视频处理中的一项重要技术&#xff0c;它可以有效地减少视频中由于相机震动或手…

华为matebook 14安装ubuntu双系统

一、准备u盘 首先格式化u盘(选择FAT32) 二、确认电脑类型 键盘按下win+r(win:开始键/也就是Windows的标志那个键),在输入框内输入msinfo32后,回车确认 确定自己电脑 硬盘 的类型: 在显示屏下方的搜索框内搜索“计算机管理” 点击进入后,再点击左边列表内的“磁…

拉普拉斯IPO:荣获国家级专精特新和国家级制造业单项冠军殊荣

近期&#xff0c;拉普拉斯荣获国家级专精特新和国家级制造业单项冠军的殊荣&#xff0c;这无疑是对其在技术和发展方面的肯定。这些荣誉证明了拉普拉斯在光伏行业的卓越表现和持续创新&#xff0c;以及其在国内制造业中的领先地位&#xff0c;进一步彰显了拉普拉斯在技术研发和…

智慧浪潮下的产业园区:洞察智慧化转型如何打造高效、绿色、安全的新园区

目录 一、引言 二、智慧化转型的内涵与价值 三、打造高效园区的智慧化策略 1、建设智能化基础设施 2、推广智能化应用 3、构建智慧化服务平台 四、实现绿色园区的智慧化途径 1、推动绿色能源应用 2、实施绿色建筑设计 3、加强环境监测与治理 五、保障园区安全的智慧…

【办公类-22-14】周计划系列(5-6)“周计划-06 19周的周计划教案合并打印PDF(最终打印版))

背景需求&#xff1a; 花了十周&#xff0c;终于把周计划教案的文字都写满、加粗、节日替换了。为了便于打印&#xff0c;我把19周的周计划教案全部合并在一起PDF。制作打印用PDF 思路 1、周计划是单独打印一张&#xff0c;因此要在第2页插入空白页&#xff0c; 2、教案有3页…

[计算机效率] 截图工具:FastStone Capture

3.19 截图工具&#xff1a;FastStone Capture FastStone Capture是一款功能强大的屏幕捕捉软件&#xff0c;体积小巧、功能强大&#xff0c;不但具有常规截图等功能&#xff0c;更有从扫描器获取图像&#xff0c;和将图像转换为PDF文档等功能。 截屏功能&#xff1a;支持全屏截…

【Python数据库】MongoDB

文章目录 [toc]数据插入数据查询数据更新数据删除 个人主页&#xff1a;丷从心 系列专栏&#xff1a;Python数据库 学习指南&#xff1a;Python学习指南 数据插入 from pymongo import MongoClientdef insert_data():mongo_client MongoClient(hostlocalhost, port27017)co…

Git变更账户、查看账户

1、变更账户 &#xff08;1&#xff09;修改当前文件夹用户 git config user.name “新用户名” git config user.email “新邮箱” &#xff08;2&#xff09;修改全局git用户 git config - -global user.name “新用户名” git config - -global user.email “新邮箱”…

计算机网络——初识网络

一、局域网与广域网 1.局域网&#xff08;LAN&#xff09; 局域网&#xff1a;即Local Area Network&#xff0c;简称LAN。Local即标识了局域⽹是本地&#xff0c;局部组建的⼀种私有⽹络。局域⽹内的主机之间能⽅便的进⾏⽹络通信&#xff0c;⼜称为内⽹&#xff1b;局域⽹和…

【c++】----STL简介string

目录 1. 什么是STL 2. STL的版本 3. STL的六大组件 4.STL的缺陷 5.string类 1. 为什么学习string类&#xff1f; 6.string类的常用接口说明&#xff08;下面我们只讲解最常用的接口&#xff09; 1.string 常见构造 2.string类的遍历 iterator 迭代器遍历 &#xff08;…