JavaSE-多线程(2)- 锁

JavaSE多线程 编写一个类,直接继承java. lang. Thread,重写run方法。 阅读详情

JavaSE-多线程(2)- 锁

synchronized

举例说明:在 SynChronizedTest 类中有一个 count 变量,有两个线程同时对count进行 ++ 操作,希望结果应该为线程每访问一次count +1 ,最终count 值为 2

package com.hs.example.base.multithread.day01;

public class SynChronizedTest implements Runnable{

    private int count = 0;

    public /*synchronized*/ void  countNum(){
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count++;
        System.out.println(count);
    }

    @Override
    public void run() {
        countNum();
    }

    public static void main(String[] args) {
        SynChronizedTest synChronizedTest = new SynChronizedTest();
        new Thread(synChronizedTest).start();
        new Thread(synChronizedTest).start();
    }
}

但是却出现如下状况,原因在于,两个线程同时访问count,count初始值都为0,经过睡眠后,count同时加1,导致最后结果为1(测试结果不一定为1)

1
1

Process finished with exit code 0

如何避免以上状况出现,这时候就需要用到锁,如下:

public synchronized void  countNum(){
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count++;
        System.out.println(count);
    }

以上 synchronized 锁定的是当前this对象(即synChronizedTest对象)代码添加 synchronized 后的意思是访问countNum方法需要获得synChronizedTest对象这把锁,以上例子如果改成下面这样,则synchronized锁定的是o这个对象

package com.hs.example.base.multithread.day01;

public class SynChronizedTest2 implements Runnable {

    private int count = 0;
    private final Object o = new Object();

    public void countNum() {
        synchronized (o) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            count++;
            System.out.println(count);
        }
    }

    @Override
    public void run() {
        countNum();
    }

    public static void main(String[] args) {
        SynChronizedTest2 synChronizedTest = new SynChronizedTest2();
        new Thread(synChronizedTest).start();
        new Thread(synChronizedTest).start();
    }
}

synchronized 如果加在 static方法上则锁定的是 SynChronizedTest.class对象

 public static synchronized void countNum() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count++;
        System.out.println(count);
    }

重入锁

简单理解为同一个线程可以对同一把锁进行重复加锁,例如:调用m1方法需要获得reentrantLock 锁对象,在m1方法内部调用的m2方法同样需要获得reentrantLock 锁对象,线程在执行时可以重复获得该锁,即重入

public class ReentrantLock implements Runnable{

    public synchronized void m1(){
        System.out.println("m1");
        m2();
    }

    public synchronized void m2(){
        System.out.println("m2");
    }

    @Override
    public void run() {
        System.out.println("ReentrantLock test");
        m1();
    }

    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        new Thread(reentrantLock).start();
    }
}

异常释放锁

以下程序中,有t1,t2两个线程,从执行结果可以看出,当某个线程执行后,另一个(或多个)线程会等待其执行结束后再执行

public class ExceptionLockTest implements Runnable {

    public synchronized void m() {
        int i = 0;
        while (i < 10) {
            System.out.println(Thread.currentThread().getName() + " i: " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            i++;
        }
    }

    @Override
    public void run() {
        m();
    }

    public static void main(String[] args) {
        ExceptionLockTest exceptionLockTest = new ExceptionLockTest();
        new Thread(exceptionLockTest, "t1").start();
        new Thread(exceptionLockTest, "t2").start();
    }
}
t2 i: 0
t2 i: 1
t2 i: 2
t2 i: 3
t2 i: 4
t2 i: 5
t2 i: 6
t2 i: 7
t2 i: 8
t2 i: 9
t1 i: 0
t1 i: 1
t1 i: 2
t1 i: 3
t1 i: 4
t1 i: 5
t1 i: 6
t1 i: 7
t1 i: 8
t1 i: 9

假如上述程序出现异常,那么刚开始执行的线程会释放锁,另外的线程就可以继续执行了,如下:

public class ExceptionLockTest implements Runnable {

    public synchronized void m() {
        int i = 0;
        while (i < 10) {
            System.out.println(Thread.currentThread().getName() + " i: " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(i==5){
                int a = i/0;
            }
            i++;
        }
    }

    @Override
    public void run() {
        m();
    }

    public static void main(String[] args) {
        ExceptionLockTest exceptionLockTest = new ExceptionLockTest();
        new Thread(exceptionLockTest, "t1").start();
        new Thread(exceptionLockTest, "t2").start();
    }
}

t2 i: 0
t2 i: 1
t2 i: 2
t2 i: 3
t2 i: 4
t2 i: 5
t1 i: 0
Exception in thread "t2" java.lang.ArithmeticException: / by zero
	at com.hs.example.base.multithread.day01.ExceptionLockTest.m(ExceptionLockTest.java:15)
	at com.hs.example.base.multithread.day01.ExceptionLockTest.run(ExceptionLockTest.java:23)
	at java.lang.Thread.run(Thread.java:745)
t1 i: 1
t1 i: 2
t1 i: 3
t1 i: 4
t1 i: 5
Exception in thread "t1" java.lang.ArithmeticException: / by zero
	at com.hs.example.base.multithread.day01.ExceptionLockTest.m(ExceptionLockTest.java:15)
	at com.hs.example.base.multithread.day01.ExceptionLockTest.run(ExceptionLockTest.java:23)
	at java.lang.Thread.run(Thread.java:745)

锁升级

偏向锁(在对象头MarkWord位置记录当前线程id) -> 自旋锁(如果有其他线程竞争则升级,默认自旋10次) -> 重量级锁(如果升级为自旋锁后线程还未获得锁或自旋时间过长则升级为重量级锁)

自旋锁与重量级锁的区别

  • 自旋锁只需要访问用户态不需要访问内核态,但是会消耗CPU资源,如果需要获得锁才能执行的方法执行时间较短或者线程较少时适合采用自旋锁
  • 重量级锁访问内核态,需要向操作系统申请锁资源,比较消耗时间,重量级锁的使用不消耗CPU资源,它会让没有获得锁的线程阻塞进入等待队列,所以对于线程多,方法耗时长的情况更适合使用重量级锁

内核态用户态是什么

操作系统对程序的执行权限进行分级,分别为用户态和内核态。用户态相比内核态有较低的执行权限,很多操作是不被操作系统允许的,简单来说就是用户态只能访问内存,防止程序错误影响到其他程序,而内核态则是可以操作系统的程序和普通用户程序

内核态: cpu可以访问计算机所有的软硬件资源
用户态: cpu权限受限,只能访问到自己内存中的数据,无法访问其他资源

参考:https://blog.youkuaiyun.com/weixin_43776652/article/details/116400370

关于锁可以查看:
https://www.jianshu.com/p/0c01191c548d

https://www.longyating.com/lock/

《JavaSE系列教程》 本专栏内容是为零基础正在学习Java的学习者量身定制的学习路线及方案,本教程字数超20w+,插图超过400+,知识体系极其全面,案例极其丰富。本配备有专门的学习群及学习视频,读者可加学习群与正在学习该阶段的人一同学习,有任何不懂的也可以观看于此教程配套的学习视频。 阅读详情

相关推荐

ISA-95(S95)标准详解

ISA-95是制造业系统集成的“通用语言”,通过分层模型和信息流规范,打通企业计划层与设备控制层,成为实现数字化工厂的核心标准之一。其与ISA-88的协同应用,可进一步优化生产执行与资源管理的效率。标准,旨在解决企业商业系统(如ERP)与工业控制系统(如MES、SCADA)之间的集成问题。

「东哥说MES」 专注于MES制造执行系统,为你拆解核心架构、功能模块及与ERP/PLC的集成逻辑。提供从入门到精通的系列干货、精选行业报告与实用工具,构建你的数字化知识体系,关注我,用实战经验照亮你的数字化之路。 3737

JavaSE-Lock锁的获取和死锁

        这篇博客主要总结死锁以及Lock锁的获取多线程死锁        Java的线程死锁是一个十分经典的问题,因为不同的线程都在等待根本不可能被释放的锁,从而导致所有任务都无法继续完成,就会出现死锁的情况。所以,在多线程编程中,”死锁“是必须要避免的,因为会造成程序的卡死。        首先先举一个死锁的例子:class MyThread implements Runnable{ ...

Synchro 明净翼 的博客 332

c#窗体应用(.NET Framework)项目对Yaml文件进行写入与读取,Yaml数据转换成json

用到的技术与版本准备工作Yaml数据在C#中进行定义对Yaml文件的读取与写入代码的添加窗体控件控制操作写入数据到Yaml文件读取Yaml文件数据Yaml数据转换成json改进——对yaml文件读取时根据yaml文件中的键进行获取,对c#中怎么取名字无关yaml文件中多个数据读取遇到的问题总结的小点参考的文章在对Yaml文件进行读取前,先将Yaml文件中的数据结构在c#中进行定义,以便后面更好的读取。这里对这四个类型进行举例(这里为了想看看这四个类型到Yaml文件的格式是什么样子的)

永远年轻 1587

Java多线程(三)

主要介绍线程的通信以及JDK 5.0新增的两种创建多线程的方式的使用。

m0_53452634的博客 374

OpenClaw 多代理协同工作模式配置指南

OpenClaw 采用。

形上得其象,形下合于数;阴阳自济,玄理自明。 1万+

DeepSeek赋能公文写作:从高效成文到精准传情的全维度指南

摘要:AI赋能公文写作的精准化实践 公文写作长期面临框架混乱、素材匮乏、表达不规范、修改低效等痛点。DeepSeek等AI工具通过"精准指令+分步赋能"模式实现突破:首先明确公文的目的性、逻辑性和规范性特征;其次采用包含场景、类型、目的等要素的指令模板;再分四步实施:框架搭建确保层次分明,内容填充解决素材问题,表达优化适配不同语体,合规校验把关格式规范。典型案例显示,AI能将数据罗列转化为"数据+成果+价值"的生动表述,使公文既规范又具感染力。这种AI赋能的写作方法显

通俗易懂学IT 233

JavaSE(21)——java的各种锁详细介绍

java的各种锁详细介绍 1. 乐观锁和悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度。在java和数据库中都有实际应用。 对于一个数据的并发操作 悲观锁认为,自己在使用数据的时候一定有别的线程来修改数据,因而在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。 乐观锁认为,自己在使用数据的时候不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据

phg739436146的博客 356

【深度学习新浪潮】AI 智能眼镜关键视觉技术、技术栈及开源项目全解析

Meta新款智能眼镜在演示中暴露出的AI误判和延迟问题,揭示了端侧视觉与多模态算法落地的核心瓶颈。本文从算法工程视角解析了AI智能眼镜的三大关键技术:感知增强(多帧降噪、HDR成像)、场景解析(轻量化目标检测、语义分割)和空间定位(视觉SLAM、ToF辅助),并梳理了完整的技术栈架构,包括硬件适配、驱动优化和框架选型。文章还提供了高价值开源项目参考,如OpenXR和ORB-SLAM3,为端侧视觉算法落地提供实操指南,助力开发者攻克算力约束下的实时性、精度和功耗平衡难题。

专注:太空算力、AI infra、异构调度、大模型成本工程 530

JavaSE(20)——java锁机制

java锁机制 1. synchronized锁 1.1 定义 synchronized是java的一个关键字,它能够将代码块(方法)锁起来 它使用起来是非常简单的,只要在代码块(方法)添加synchronized,即可以实现同步功能。 public sychronized void test(){} synchronized是一种互斥锁 一次只能允许一个线程进入被锁住的代码块 synchronized是一种内置锁/监视器锁 Java中每一个对象都有一个内置锁 (监视器,也可以理解成锁标

phg739436146的博客 513

【Python机器学习】零基础掌握RFECV特征选择

通过应用算法,有效地识别了影响购买意愿的关键特征(浏览时长和点击数)和历史货币流通的主要因素(年代、人口和货币流通量)。这样的特征选择不仅提高了模型的解释能力,还可能用于电商推荐系统和历史研究的优化。优点总结,这种方法可以高效地找出对目标变量有最大影响的特征,进而可以用于各种实际应用场景,如电商推荐和历史研究。优点名称对应描述说明高解释性易于理解哪些特征最为重要泛化性能强通过交叉验证提高模型的稳健性应用场景多样可用于电商、金融、历史研究等多个领域。

Mr数据杨 1998

vue3 - vite报错TypeError: crypto.hash is not a function(vue3+vite启动运行提示错误,项目无法启动且打包报错失败,详细解决排查方案教程)

vue3 vite 报错,vue3+vite启动报错:TypeError: crypto.hash is not a function,创建vue3+vite项目时报错TypeError: crypto.hash is not a function,如何解决这个问题,VUE3+VITE报错crypto.hash,vue3运行报错,vite运行报错,vue3打包报错,vite打包报错,vue3新建项目无法运行,vue3 vite创建项目直接报错了,node版本不兼容,修改了node版本还是不行,依旧报错,一直

✅ 精选推荐文章 1万+

JavaSE-多线程(2.1)- 锁举例1(synchronized)

JavaSE-多线程(2.1)- 锁举例1 package com.hs.example.base.multithread.day01; import java.util.LinkedList; /** * 自定义容器,固定容量最大值为MAX_COUNT,运行多线程并发put和get * @param <T> */ public class SynchronizedTest4<T> { final LinkedList<T> lists = new L

sql2008help的博客 397

基于simulink的BMS系统中电池单体故障隔离与恢复建模

本文介绍了使用Simulink构建BMS电池单体故障诊断与容错控制模型的方法。主要内容包括:1)搭建12串锂电池组模型;2)实现单体故障注入(过压、断线等);3)设计故障诊断与隔离模块(采用Stateflow状态机);4)开发恢复判断逻辑(需满足电压、温度等条件);5)系统监控与仿真设置。文章还提供了工程实践建议,如防环流设计、通信冗余等,并指出进阶方向(多故障处理、AI预警等)。该模型适用于新能源汽车、储能系统的BMS设计,可提高系统可靠性和安全性。

xiaoheshang_123的博客 140

JavaSE-多线程(2.2)- 锁举例2(Reentrant Lock )

JavaSE-多线程(2.2)- 锁举例2(Reentrant Lock ) package com.hs.example.base.multithread.day01; import java.util.LinkedList; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /**

sql2008help的博客 188

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

【从入门到起飞】JavaSE—多线程(2)(lock锁,死锁,等待唤醒机制)

比如下面这一段代码我们在上一篇文章中讲过,那么我们要想自定义运行过程,比如手动打开或者手动关闭,那么就应该使用lock锁。

小吉妙妙屋 323

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

【JavaSE】多线程之常见的锁策略

这篇文章主要介绍一下多线程中常见的几种锁,以便大家更好的了解和使用锁tip:此处的锁策略不是和Java强相关的,其他语言只要是涉及到并发编程都可以谈到这样的锁策略。

stillaliveQEJ的博客 867

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【JavaSE】偏向锁、轻量级锁和重量级锁,如何获取锁,如何撤销锁。

一、java对象头 锁的获取和撤销会关系到对象头,所以先来看看对象头。 Java对象头Mark Word字段存放内容: 根据竞争状态的激烈程度,锁会自动进行升级,锁不能降级(为了提高锁获取) 一、偏向锁 由于老版本的内建锁synchronized存在最大的问题:在存在线程竞争的情况下会出现线程的阻塞以及唤醒带来的性能问题,这是一种互斥同步(阻塞同步)。 大多数情况下,锁不仅不存在多线程竞争...

qq_39487033的博客 2675

【JavaSE】【多线程】进阶知识

锁策略,synchronized特性,CAS,JUC组件

yj20040627的博客 4955

JavaSE之多线程2

多线程技术线程的休眠线程堵塞线程中断jvm里线程的状态守护线程与用户线程线程安全问题解决线程不安全的三种加锁机制隐式锁同步代码块同步方法显式锁公平锁与非公平锁线程死锁 线程的休眠 public class Demo { public static void main(String[] args) throws InterruptedException { // 线程休眠 sleep for (int i = 0; i < 10; i++) {

sclieshare的博客 1160

JavaSE多线程之卖电影票案例

JavaSE多线程之卖电影票案例 1.继承Thread类的方式卖电影票 A:案例演示 需求:某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,请设计一个程序模拟该电影院售票。 通过继承Thread类实现 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2020060620085618.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6L

ITzhazhassc的博客 1858

JavaSE后阶(多线程)

Java多线程

2401_85776998的博客 1078

JavaSE 总复习:语法到多线程全梳理

JavaSE 高效复习指南(150字摘要) 本文提出结构化复习JavaSE的方法,强调从问题解决角度切入而非死记API。将JavaSE划分为12个核心模块,每个模块明确其解决的问题:基础语法构建代码基础,面向对象组织代码结构,集合管理数据,IO处理文件读写,多线程实现并发等。复习重点包括:掌握最小实现代码、识别常见错误、设计自测方案。特别提醒关注面向对象、集合、IO和多线程等核心模块,同时注意JDK版本差异。文章采用"问题导向+代码实践"的方式串联知识点,并提供详细笔记链接供深入查阅。 (150字)

一个持续进化的java+ai学习者博客:AI Agent 工具链(Codex、Harness、Claude Code、MCP、Skills)实战笔记 + 后端开发教程,每周稳定更新。 4908

怎样正确的度过JavaSE阶段真的很重要!(详细知识内容+资料)

不要小看JavaSE的这些基础章节,打好基础很重要!巧了,我这里涵盖了所有Java基础!

奈何的人生 2万+

JavaSE(多线程和线程池)知识点总结

​ 线程就是操作系统能够进行运算调度的最小单位,它被包含在进程(进程是程序的基本执行实体,任务管理器种选择的进程就可以看到每个软件的进程)中,是进程中实际运作的单位。​ 比如:360杀毒软件,包括木马查杀、电脑清理、系统修复功能。其中360杀毒软件就是进程,其中的功能就是线程。​ 简单理解:应用软件种相互独立,可以同时运行的功能就是线程。

weixin_46119796的博客 1745

JavaSE超详细笔记-多线程篇-基于黑马

假如计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。他的作用就是去调用main方法,并执行里面的代码,之前在main方法里的代码,其实都是运行在main线程当中。接下来,以线程基础,线程优先级,守护线程,礼让线程,插入线程的几个角度去拆分。

超级苦力怕的博客 1255

JavaSE多线程笔记

javase多线程笔记

cc_1113的博客 916
上一篇: JavaSE-多线程(1)- 线程概念
下一篇: JavaSE-多线程(3)- volatile
sql2008help
博客等级 码龄11年 80粉丝 145原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值