线程死锁、锁死、饥饿、活锁讲解

Java线程饥饿:深度解析与系统优化指南 线程饥饿是Java并发编程中一个隐蔽但危害严重的性能问题,指某些线程因长期无法获取必要资源(如CPU时间片、锁、I/O等)而无法正常执行任务。本文全面剖析了线程饥饿的成因、表现、诊断方法和解决方案。线程饥饿的根本原因在于资源分配策略不合理,导致高优先级线程垄断资源,低优先级线程长期等待。典型场景包括不合理的线程优先级设置、非公平锁竞争、不合理的线程池配置以及资源泄漏。诊断线程饥饿可通过JVM内置工具、可视化工具和自定义监控实现,关键指标包括线程状态持续时间、锁竞争指标和CPU时间分配。解决方案包括启用公平锁 阅读详情

死锁

概念

如果两个或者更多的线程因为相互等待对方而被永远暂停,线程的生命周期变成了BLOCKED或者WAITING,则我们称这些线程产生了死锁(DeadLock)

哲学家就餐问题

现在来用代码描述一下“哲学家就餐问题”,先将问题简化,假设只有两个哲学家面对面坐着,每个哲学家吃饭都先拿自己左手边的筷子,再拿右手边;当哲学家A拿起他左手边的的筷子,打算拿右边的时,哲学家B拿起了他自己左手边的筷子,而其正好是哲学家A的右手边,由于双方都等着拿自己右手边筷子,但自己又不会先放下左手中的筷子,这就导致了“死锁”。
1、哲学家的抽象类

public abstract class AbsPhilosopher extends Thread {

    protected String id;
    protected Chopstick left;
    protected Chopstick right;


    public AbsPhilosopher(String id, Chopstick left, Chopstick right) {
        this.id = id;
        this.left = left;
        this.right = right;
    }


    @Override
    public void run() {
        for (; ; ) {
            think();
            eat();
        }

    }

    protected abstract void eat();

    protected void think() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("the %s is thinking\n", id);
    }

    protected void doEat() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.printf("the %s is eating\n", id);
    }
}

2、具有死锁的哲学家实现类

public class DeadLockPhilosopherImpl extends AbsPhilosopher {


    public DeadLockPhilosopherImpl(String id, Chopstick left, Chopstick right) {
        super(id, left, right);
    }

    @Override
    protected void eat() {
        synchronized (left) {
            left.pickup();
            synchronized (right) {
                right.pickup();
                //两根筷子同时拿起开始吃饭
                doEat();
                right.putDown();
            }
            left.putDown();
        }
    }
}

3、筷子类

public class Chopstick {

    public final int id;

    public Chopstick(int id) {
        this.id = id;
    }

    public void pickup(){
    }

    public void putDown(){

    }
}

4、客户端

public class PhilosopherTest {

    public static void main(String[] args) {

        int nums = 2;
        //两个人,两只筷子
        Chopstick[] chopsticks = new Chopstick[nums];

        for (int i = 0; i < 2; i++) {
            chopsticks[i] = new Chopstick(i);
        }

        //创建两个哲学家
        for (int i = 0; i < nums; i++) {
            AbsPhilosopher philosopher0 = new DeadLockPhilosopherImpl(String.valueOf(i), chopsticks[i], chopsticks[(i + 1) % nums]);
            AbsPhilosopher philosopher1 = new DeadLockPhilosopherImpl(String.valueOf(i), chopsticks[i], chopsticks[(i + 1) % nums]);

            philosopher0.start();
            philosopher1.start();
        }

    }
}

死锁的检测方式

上述问题出现了死锁,有两种检测方式
1、启动客户端之后,在控制台输入jps,找到启动类的pid,进行jstack,即可发现死锁的产生:
在这里插入图片描述
2、另外一种本地检查死锁的方式,如果是win电脑的话,可以按win+r,输入jconsole,选择执行的demo后按如下操作可以快速定位死锁。
在这里插入图片描述

死锁的产生条件

资源互斥

涉及的资源必须是独立的,即一个资源只能被一个线程访问。比如一根筷子只能被一个哲学家使用。

资源不可抢夺

涉及到的资源只能被线程持有者主动释放,其他线程无法抢夺。比如筷子只能由当前哲学家进行放下,其他哲学家不能抢夺。

占用并等待资源

涉及到的线程当前至少持有一份资源,并等待其他线程持有的资源,在资源等待中,当前线程并不释放自己持有的资源。比如哲学家A拿起自己左手的筷子,并申请他右手边的筷子,但并不会放下左手中的筷子。

循环等待资源

涉及的线程必须在等待别的线程的资源,而这些线程又等待第一个线程的资源。第一个哲学家在等待第二个哲学家左手的筷子,第二个哲学家在等待第一个哲学家的左手的筷子。

死锁的规避

死锁的四个产生条件时必要不充分条件,产生死锁的话,这四个条件一定要同时成立,但这四个条件同时成立不一定产生死锁。所以只要消除死锁的任意一个条件就可以规避死锁。
粗锁法:使用一个粗粒度的锁来代替多个锁,从而消除“占用并等待资源”和“循环等待资源”这两个条件。

public class GlobalLockPhilosopherImpl extends AbsPhilosopher {
	//使用static变量
    private static final Object GLOBAL_LOCK = "lock";

    public GlobalLockPhilosopherImpl(String id, Chopstick left, Chopstick right) {
        super(id, left, right);
    }
    @Override
    protected void eat() {
        synchronized (GLOBAL_LOCK) {
            left.pickup();
            right.pickup();
            //两根筷子同时拿起开始吃饭
            doEat();
            right.putDown();
            left.putDown();
        }
    }
}

粗锁法有一个缺点是会导致资源的浪费,因为同一时刻只能有一个线程使用资源,也就是同一时刻只能有一个哲学家就餐。假设有5个哲学家,当有1个哲学家就餐时,还剩下3根筷子,其实还够一个哲学家就餐的。

锁排序法:相关线程使用全局统一的顺序去申请锁。假设有多个线程要去申请资源,则可以给这些资源排上序号,让这些线程按照序号从小到大或者从大到小去申请,则可以打破“循环等待资源”这个条件。哲学家就餐导致死锁的一个原因是哲学家必须先拿起自己左手的筷子,再拿起右手的筷子。我们给这些筷子排上序号,当一个哲学家就餐时,他必须先拿起序号小的筷子,再拿起序号大的筷子,而不是先左手再右手。

public class SortLockPhilosopherImpl extends AbsPhilosopher {

    private Chopstick one;
    private Chopstick theOther;

    private static final Object GLOBAL_LOCK = "lock";

    public SortLockPhilosopherImpl(String id, Chopstick left, Chopstick right) {
        super(id, left, right);
		//对资源进行排序
        int leftHash = Objects.hash(left);
        int rightHash = Objects.hash(right);

        if (leftHash < rightHash) {
            one = left;
            theOther = right;
        } else if (leftHash > rightHash) {
            one = right;
            theOther = left;
        } else { //hash相同
            one = null;
        }
    }

    @Override
    protected void eat() {
        if (Objects.nonNull(one)){
            synchronized (one){
                one.pickup();
                synchronized (theOther){
                   theOther.pickup();
                    eat();
                    theOther.putDown();
                }
                one.putDown();
            }
        }else{
            synchronized (GLOBAL_LOCK) {
                left.pickup();
                right.pickup();
                doEat();
                right.putDown();
                left.putDown();
            }
        }
    }
}

使用ReentrantLock.tryLock(long,TimeUnit):为申请锁设置一个超时时间,在超时时间内,如果获取锁则返回true,没有则返回false。可以打破“占用并等待资源这个条件”。

public class TryLockPhilosopherImpl extends AbsPhilosopher {
    private static Map<Chopstick, ReentrantLock> LOCK_MAP = new ConcurrentHashMap<>();

    public TryLockPhilosopherImpl(String id, Chopstick left, Chopstick right) {
        super(id, left, right);
        LOCK_MAP.putIfAbsent(left, new ReentrantLock());
        LOCK_MAP.putIfAbsent(right, new ReentrantLock());

    }

    @Override
    protected void eat() {
        if (pickUp(left) && pickUp(right)) {
            try {
                doEat();
            } finally {
                putDown(left);
                putDown(right);
            }
        }
    }

    private boolean pickUp(Chopstick chopstick) {
        ReentrantLock lock = LOCK_MAP.get(chopstick);
        boolean tryLock = false;
        try {
            tryLock = lock.tryLock(30, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
            //当前线程拿起另一只筷子,使其放下
            Chopstick theOther = chopstick == left ? right : left;
            if (LOCK_MAP.get(theOther).isHeldByCurrentThread()) {
                theOther.putDown();
                LOCK_MAP.get(theOther).unlock();
            }
            return false;
        }
        if (tryLock) {
            chopstick.pickup();
            return true;
        } else {
            return false;
        }
    }

    private void putDown(Chopstick chopstick) {
        ReentrantLock lock = LOCK_MAP.get(chopstick);
        chopstick.putDown();
        lock.unlock();
    }
}

死锁的恢复

以上是死锁的规避方法,但如果死锁已经产生了,需要具有恢复的手段。如果代码使用的是内部锁或者Lock.lock(),则无法恢复,只能重启虚拟机。但如果代码中使用的是Lock.lockInterruptibly()实现的,那是可以进行恢复的。

public class DeadLockDetector extends Thread {
    static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
    private final long monitorInterval;

    public DeadLockDetector(long monitorInterval) {
        super("DeadLockDetector");
        setDaemon(true);
        this.monitorInterval = monitorInterval;
    }

    public DeadLockDetector() {
        this(2000);
    }

    public static ThreadInfo[] findDeadLockThreads() {
        long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
        return null == deadlockedThreads ? new ThreadInfo[0] : threadMXBean.getThreadInfo(deadlockedThreads);
    }

    public static Thread findThreadById(long threadId) {
        for (Thread thread : Thread.getAllStackTraces().keySet()) {
            if (thread.getId() == threadId) {
                return thread;
            }
        }
        return null;
    }

    public static boolean interruptThread(long threadId) {
        Thread thread = findThreadById(threadId);
        if (null != thread) {
            thread.interrupt();
            return true;
        }
        return false;
    }

    @Override
    public void run() {
        ThreadInfo[] threadInfos;
        ThreadInfo threadInfo;
        int i = 0;
        for (; ; ) {
            //检测系统中是否存在死锁
            threadInfos = DeadLockDetector.findDeadLockThreads();
            if (threadInfos.length > 0) {
                //选取任意一个死锁的线程,给它发送中断请求
                threadInfo = threadInfos[i++ % threadInfos.length];
                DeadLockDetector.interruptThread(threadInfo.getThreadId());
                continue;
            } else {
                i = 0;
                System.out.println("No deadLock found");
            }
            try {
                //每隔一段时间进行一次死锁的检测
                Thread.sleep(monitorInterval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

大概思想是建立一个心跳线程,间断性的去检测jvm有没有死锁产生,有的话就发送一个中断请求。
所以把哲学家就餐中加锁的代码换成如下:

    private boolean pickUp(Chopstick chopstick) {
        ReentrantLock lock = LOCK_MAP.get(chopstick);
        try {
            lock.lockInterruptibly();
            chopstick.pickup();
            return true;
        } catch (InterruptedException e) {
            //当前线程拿起另一只筷子,使其放下
            Chopstick theOther = chopstick == left ? right : left;
            theOther.putDown();
            LOCK_MAP.get(theOther).unlock();
            return false;
        } finally {
            lock.unlock();
        }
    }

锁死

由于唤醒等待线程所需的条件永远无法成立,或者其他线程无法唤醒该线程而一直处于非运行状态,我们称这个线程被锁死。
锁死和死锁的最终结果很相似,都是线程无法运行。但二者产生的条件是不同的,死锁产生的条件在如上四个;锁死产生的条件分为信号丢失锁死和嵌套监视器锁死。

信号丢失锁死

信号丢失锁死是没有相应的通知线程来唤醒等待线程,从而使线程一直等待下去。最常见的例子就是线程执行wait()/notify()的时候,没有对保护条件进行判断,但先执行了nofity,再执行的wait,从而错过了线程唤醒,导致等待线程一直等待下去。错误的代码如下:

  synchronized (someObject) {
            //调用someObject来暂停当前线程
            someObject.wait();
            //其它线程执行了notify,使条件满足时,执行目标动作
            doAction();
        }

正确的代码如下:

   //原子操作,在调用之前需要新获取内部锁
    synchronized (someObject){
        while(保护条件不成立){
            //调用someObject来暂停当前线程
            someObject.wait()
        }
        //其它线程执行了notify,使条件满足时,执行目标动作
        doAction();
    }

嵌套监视器锁死

嵌套监视器锁死是嵌套锁导致等待线程永远无法被唤醒的一种活性障碍。
在这里插入图片描述
如上情况,左边是等待线程,右边是通知线程。当语句2准备执行的时候,语句1已经在执行了,从而导致通知线程被阻塞,当等待线程执行完语句1之后,并不会释放monitorX,继续执行到monitorY.wait()处,从而使等待线程阻塞,但是因为等待线程没有释放monitorX资源,导致通知线程也无法执行monitorY.notifyAll(),因此等待线程会一直等待下去。这种由于嵌套锁导致通知线程始终无法唤醒等待线程的活性障碍被称为嵌套监视器锁死。

线程饥饿

线程饥饿指的是线程一直无法获得其所需的资源而导致任务一直无法进展的一种活性障碍。
产生线程饥饿的一般条件都是非公平锁的使用。死锁也属于线程饥饿,因为死锁也是因为某种情况从而导致无法获取资源。导致线程饥饿的条件仅仅是无法获取资源,比如显示锁(非公平锁)的使用,但这并不意味会导致死锁。

活锁

没有阻塞当前线程申请资源,但申请资源一直未成功,也就是当前线程一直处于做无用功的状态,这是活锁。----屡战屡败,屡败屡战。

检查java死锁的三种方式 介绍了java检验死锁的三种方式 阅读详情

相关推荐

知识点: Java公平锁与非公平锁 原理讲解ReentrantLock 锁的饥饿效应及解决办法

公平锁与非公平锁理论前言AQS公平锁非公平锁ReentrantLock 使用ReentrantLock 解决饥饿效应 本文知识: 公平锁与非公平锁理论 AQS的理论与原理讲解 公平锁与非公平锁原理讲解 ReentrantLock的使用 非公平锁饥饿效应解决方法 在上篇中分析了Java并发编程中悲观锁与乐观锁的实现算法,并分析了原子类中使用CAS算法实现乐观锁以及ABA、自旋等问题。 延续上篇继续导论Java ReentrantLock锁,如果实现公平锁与非公平锁。 前言 公平锁:多个线程申请锁时是相对公

码农杰森 2953

线程的死锁、活锁和饥饿现象

线程的活锁、死锁和饥饿现象

m0_62609939的博客 3038

Python连接高斯数据库踩坑实录:从SASL报错到SSL安全连接的完整指南

本文详细记录了Python连接高斯数据库时遇到的SASL authentication报错及其解决方法。通过剖析SASL认证机制,对比了修改数据库配置、使用官方驱动等方案的利弊,并重点提供了通过自动化脚本生成SSL证书,实现安全、免密连接的完整指南,帮助开发者彻底解决连接难题。

weixin_28340315的博客 438

Java线程饥饿

当连续不断拒绝线程访问资源并因此无法取得进展时,就会发生饥饿。当贪婪的线程长时间使用共享资源时,通常会发生这种情况。如果这种情况持续了很长时间,则线程没有获得足够的CPU时间或对资源的访问将无法取得足够的进展,从而导致线程不足。线程饥饿的可能原因之一是不同线程或线程组之间的线程优先级不正确。 另一个可能的原因可能是使用非终止循环(无限循环)或在特定资源上等待过多时间,同时保留了其他线程所需的关键锁。 通常建议尽量避免修改线程优先级,因为这是导致线程饥饿的主要原因。一旦开始使用线程优先级调整应用程序,它就

allway2的博客 3022

EDA工具安装第一步:Synopsys Installer的配置与图形化界面使用详解

本文详细解析了EDA工具安装的关键第一步——Synopsys Installer的配置与使用。文章阐述了其作为统一部署管理器和依赖协调者的核心作用,并分步详解了如何通过图形化界面高效安装EDA工具,同时介绍了命令行批处理等进阶技巧,旨在帮助工程师快速搭建稳定的芯片设计环境。

zeta9的博客 340

5、硬件工程师笔试面试——上拉电阻、下拉电阻(2025版本)

本文系统介绍了上拉电阻和下拉电阻的原理与应用。上拉电阻通过连接电源确保电路高电平状态,常用于数字电路防抖、OC门驱动等场景;下拉电阻连接地线维持低电平,适用于低电平触发电路。文章详细分析了两种电阻的选择方法、功耗与响应速度的平衡策略,以及在高速信号传输中的影响差异。同时对比了二者的优缺点,并提供了模拟电路中的应用实例。最后给出了电阻值计算的工程方法,为硬件工程师的电路设计提供了实用参考。

XU157303764的博客 2868

Java并发一

文章目录并发编程必须会的知识点进程和线程的区别进程之间的通信方式(操作系统层面)单线程和多线程的关系线程的状态有哪几种?并发编程中常用的API线程会遇到哪些故障?死锁线程锁死信号丢失锁死嵌套监视器锁死活锁线程饥饿 并发编程必须会的知识点 单线程和多线程,进程与线程的区别 线程活性故障及其解决方法 线程调度方式 可见性,原子性以及有序性 synchronized,volatile,Atomic等关键字 线程池及阻塞队列 java.util.concurrent(简称JUC )包,此包是并发编程中常用的工具

weixin_45593271的博客 263

大模型——Coze工作流实战:一键生成像素风格视频

本文介绍了如何利用Coze平台工作流生成像素风格心理学短视频的方法。通过创建工作流、设置变量节点、调用大模型生成文案、数据格式化处理、合成音频、生成字幕等步骤,最终实现从输入主题到生成完整视频的自动化流程。文章详细展示了每个节点的具体配置方法,包括提示词编写和数据处理脚本,为读者提供了完整的像素风格视频制作解决方案。

818

0907(049天 线程集合03 线程、死\活锁、juc包)

死锁、活锁 线程饥饿问题 判定是否有锁 CAS AQS juc包中的几个小玩意

weixin_48015656的博客 574

【ComfyUI报错解决】K采样器 mat1和mat2形状不匹配错误分析与修复 mat1 and mat2 shapes cannot be multiplied (77x2048 and 4096x

如果你在 ComfyUI 里遇到K采样器报错:mat1 和 mat2 shapes cannot be multiplied确认大模型和 LoRA 是否是同一版本(SDXL vs SD1.5,不能混用)。如果用了双 CLIP 加载器,要确认加载的类型和选择的模型类型是否匹配。加载→ 类型选flux加载 SDXL 专用的 clip/t5 → 类型选sdxl避免不同版本模型和 LoRA 混搭,保持一致性。模型+LoRA+CLIP 类型必须保持同一版本,不然就会报错。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 2408

从数据库到数据仓库:数据仓库导论

本文为数据仓库导论,旨在介绍数据仓库的基本理念和应用场景,帮助读者理解数据仓库的重要性及其在企业中的实际应用。

探索大数据世界 - 深入解析数据存储、分布式计算与人工智能 2784

【无标题】线程学习(18)-多把锁下的线程问题,死锁,活锁,饥饿

多把锁的应用 减小锁粒度,提交并发度。 package com.bo.threadstudy.four; import lombok.extern.slf4j.Slf4j; /** * 多把锁的情况,以及后期的死锁,活锁,饥饿现象,哲学家就餐 */ @Slf4j public class ManyLockTest { private static final Object lock1 = new Object(); private static final Object l

key_wu的博客 213

Bert+CNN文本分类(含代码实现)

一、什么是CNN? CNN的特点: (1)特定特征位移不变性 (2)特征缩放不变性 2. CNN模型构造过程 2.1 Convolution(卷积) (1)获取关键特征(减少参数) (2)共享权重(再次减少参数) 2.2 Max Pooling(池化) 2.3 Flatten 向量转换为如图所示可以进入全连接层的向量模式 3. TextCNN 上图可理解为: 通过不同的size(如上图2、3、4等),上图红色代表 size=2,黄色...

Python,数据分析,机器学习,深度学习 1万+

面试必问系列,源码解析多线程绝对不容忽视得问题:线程活性故障

看多了各种多线程得内容,我们是不是忘记了某一个很重要得知识点——线程活性故障 线程活性故障是由于资源稀缺性或者程序自身的问题导致线程一直处于非 Runnable 状态,或者线程虽然处于 Runnable 状态但是其要执行的任务一直无法取得进展的一种故障现象 下面就来介绍几种常见类型的线程活性故障: 死锁 锁死 线程饥饿 活锁 死锁 对于死锁得问题,我们有一个非常非常好玩的问题—哲学家吃饭,干饭人干饭魂,我们就通过这个讲解引入一下 啊 关注公众号:Java架构师联盟,每日更新技术好文 假设有 5 个哲学家

Java架构师联盟 200

Open3D 基于法向量夹角的特征点提取

基于法向量夹角的特征点提取是一种在点云处理中用于识别表面变化显著区域的技术。通过计算点云中每个点的法向量与其邻域点法向量之间的夹角,可以判断点云表面的局部变化程度,并提取那些法向量变化较大的点作为特征点。这种方法特别适用于提取边缘、角点等关键几何特征。

纵马踏花向自由 1552

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

漫道多线程(二):临界区、锁与JMM

临界区 在上一章,我们就讨论过,在多线程程序中数据是脆弱的,而这些脆弱的数据在多线程的概念中就是所谓的临界区 临界区用来一种公共资源资源或者是共享享数据,可以被多个线程使用。但是每一次,只能有一个线程使用它,一旦临界区资源被占用,其他线程想要使用这个资源,就必须等待。 锁 锁的作用就是保障临界区 阻塞与非阻塞 阻塞与非阻塞是用来形容线程间的影响的。 通过临界区的定义我们可知,当一个线程占用了临界区资源,那么其他线程必须在这个临界区等待。等待会导致线程挂起,这种情况就是阻塞。 简而言之,一

钟长森的博客 435

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

多线程学习笔记(一)--多线程相关概念

强烈推荐一个大神的人工智能的教程:http://www.captainbed.net/zhanghan 前言 究竟什么时候要使用并行呢?是什么场景都可以达到我们预想的那样高性能吗?2014年底,Avoiding ping pong论坛上,Linus Torvalds提出了一个截然不同的观点,Give it up,The whole "parallel computing is the futu...

至尊宝 2万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

多线程与并发系列1- 基本概念

一、并发与并行 二、程序,线程,进程,协程 三、同步与异步 四、JAVA内存模型 JMM 五、死锁、饥饿、活锁 六、线程安全

bitree1的博客 609

操作系统——进程与线程(死锁)

1)为什么会产生死锁?产生死锁有什么条件?2)有什么办法解决死锁?

2301_80636070的博客 1510

java“锁事“ 之不同的锁讲解

java的各种锁的介绍

一个有信仰的技术人 157

深入解析 Linux 死锁:原理、原因及解决方案

例:2024 年 5 月的一个凌晨 3 点,某互联网公司运维群突然炸锅:用户反馈电商平台的 “支付接口” 彻底卡死,所有订单无法提交。值班工程师登录服务器(IP:8.142.),发现 MySQL 进程 CPU 占用 100%,但日志里没有报错;查看 PHP-FPM 进程,发现 50 个工作进程全部 “卡住”,像被施了定身咒。最终,通过内核调试工具pstack追踪线程状态,真相浮出水面 ——多线程在竞争数据库连接锁时,形成了死锁。

conkl的博客 1154

基于Java的锁、多线程、线程池并发编程

背景 操作系统 所有计算机资源是被一个程序独占的,称为裸机 能够协调程序排队的简单批处理系统 当程序遇到IO之类的阻塞时,处理器转而处理其他程序,称作多道批处理系统 给每个程序都分配一点处理器时间去轮流执行,每个程序分配到的执行时间就叫做时间片,这个过程也叫做分时处理。操作系统负责管理时间片具体设置为多大,处理器怎么切换各个程序的执行 4核、8核即多个处理器 进程 进程的两个特点:资源所有权...

byr_wy的博客 1800

《Java 高并发》01 高并发基本概念

## 基本概念 ### 同步和异步 同步和异步通常是用来形容一次方法调用。 同步方法调用一旦开始,调用者必须等到方法返回才能继续执行后续操作。 异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作。异步方法通常会在另外一个线程中"真实"执行,整个过程不会影响调用者的工作。 举例:到了饭点,我们点外卖,下单成功之后等待外卖小哥送餐。这就是同步调用。 不过,为了学习,我们在下单成功之后看了会《Java 从入门到放弃》书籍,边等待外卖小哥送餐。这就是异步调用。 ##

添砖加瓦 287

什么!有一定的学习门槛你就学不好?Java多线程,从基础到并发模型统统帮你搞定!

小编接下来会从基础概念开始到最后的并发模型由浅入深,讲解下线程方面的知识。

2401_85763924的博客 540

2024年最新JAVA并发之加锁导致的活跃性问题,java基础面试题大全带答案

手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录需要这份系统化的资料的朋友,可以点击这里获取lock();}else {@Override//表明锁已经释放@Override@Override// 使用Stream流的方式创建四个线程try {work();});

2401_84558388的博客 1111

Java 锁的机制 【入门讲解】

分类维度具体类型核心特点典型例子是否互斥互斥锁(Exclusive Lock)同一时间只允许一个线程持有锁(写操作需互斥)共享锁(Shared Lock)允许多个线程同时持有锁(读操作可共享)的读锁是否公平公平锁(Fair Lock)线程获取锁的顺序与请求顺序一致(先到先得)非公平锁(Unfair Lock)线程获取锁时可 “插队”(可能导致某些线程饥饿,但性能更高)是否可重入可重入锁(Reentrant)同一线程可多次获取同一把锁(避免自己锁死自己)

beiguo666的博客 1130
上一篇: java中“冷门”工具类的总结
下一篇: 线程的高效利用——线程池
玉带林中挂
博客等级 码龄8年 264粉丝 167原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值