(八) 共享模型之管程【活跃性】

news2024/11/15 21:37:32

一、多把锁(P114)

一间大屋子有两个功能:睡觉、学习,互不相干。
现在小南要学习,小女要睡觉,但如果只用一间屋子(一个对象锁)的话,那么并发度很低

解决方法是准备多个房间(多个对象锁)

public class TestMultiLock {
    public static void main(String[] args) {
        BigRoom bigRoom = new BigRoom();
        new Thread(() -> {
            bigRoom.study();
        },"小南").start();
        new Thread(() -> {
            bigRoom.sleep();
        },"小女").start();
    }
}

@Slf4j(topic = "c.BigRoom")
public class BigRoom {

    public void sleep() throws InterruptedException {
        synchronized (this) {
            log.debug("sleeping 2 小时");
            Thread.sleep(2);
        }
    }

    public void study()  throws InterruptedException {
        synchronized (this) {
            log.debug("study 1 小时");
            Thread.sleep(1);
        }
    }

}
改进
@Slf4j(topic = "c.BigRoom")
public class BigRoom {

    private final Object studyRoom = new Object();

    private final Object bedRoom = new Object();

    public void sleep() throws InterruptedException {
        synchronized (bedRoom) {
            log.debug("sleeping 2 小时");
            Thread.sleep(2000);
        }
    }

    public void study() throws InterruptedException {
        synchronized (studyRoom) {
            log.debug("study 1 小时");
            Thread.sleep(1000);
        }
    }

}

将锁的粒度细分:

好处:增强并发度。

坏处:如果一个线程需要同时获得多把锁,就容易发生死锁。

二、死锁

一个线程需要同时获取多把锁,这时就容易发生死锁。

【t1 线程】 获得 A对象 锁,接下来想获取 B对象的锁;

【t2 线程】 获得 B对象 锁,接下来想获取 A对象的锁。

@Slf4j(topic = "c.TestDeadLock")
public class TestDeadLock {
    public static void main(String[] args) {
        test1();
    }

    private static void test1() {
        Object A = new Object();
        Object B = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (A) {
                log.debug("lock A");
                sleep(1);
                synchronized (B) {
                    log.debug("lock B");
                    log.debug("操作...");
                }
            }
        }, "t1");

        Thread t2 = new Thread(() -> {
            synchronized (B) {
                log.debug("lock B");
                sleep(0.5);
                synchronized (A) {
                    log.debug("lock A");
                    log.debug("操作...");
                }
            }
        }, "t2");
        t1.start();
        t2.start();
    }
}

三、定位死锁

检测死锁可以使用 jconsole工具,

或者使用 jps 定位进程 id,再用 jstack 定位死锁:

  

(1)避免死锁要注意加锁顺序
(2)另外如果由于某个线程进入了死循环,导致其它线程一直等待,对于这种情况 linux 下可以通过 top 先定位到 CPU 占用高的 Java 进程,再利用 top - Hp 进程 id 来定位是哪个线程,最后再用 jstack 排查

四、哲学家就餐问题

有五位哲学家,围坐在圆桌旁。
(1)他们只做两件事,思考和吃饭,思考一会吃口饭,吃完饭后接着思考。
(2)吃饭时要用两根筷子吃,桌上共有 5 根筷子,每位哲学家左右手边各有一根筷子。
(3)如果筷子被身边的人拿着,自己就得等待

 

public class TestDeadLock {
    public static void main(String[] args) {
        Chopstick c1 = new Chopstick("1");
        Chopstick c2 = new Chopstick("2");
        Chopstick c3 = new Chopstick("3");
        Chopstick c4 = new Chopstick("4");
        Chopstick c5 = new Chopstick("5");
        new Philosopher("苏格拉底", c1, c2).start();
        new Philosopher("柏拉图", c2, c3).start();
        new Philosopher("亚里士多德", c3, c4).start();
        new Philosopher("赫拉克利特", c4, c5).start();
        new Philosopher("阿基米德", c1, c5).start();
    }
}

@Slf4j(topic = "c.Philosopher")
class Philosopher extends Thread {
    Chopstick left;
    Chopstick right;

    public Philosopher(String name, Chopstick left, Chopstick right) {
        super(name);
        this.left = left;
        this.right = right;
    }

    @Override
    public void run() {
        while (true) {
            // 尝试获得左手筷子
            synchronized (left) {
                // 尝试获得右手筷子
                synchronized (right) {
                    eat();
                }
            }
        }
    }

    Random random = new Random();
    private void eat() {
        log.debug("eating...");
        Sleeper.sleep(0.5);
    }
}

class Chopstick {
    String name;

    public Chopstick(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "筷子{" + name + '}';
    }
}

这种线程没有按预期结束,执行不下去的情况,归类为【 活跃性 】问题,除了死锁以外,还有活锁和饥饿者两种情况

 

五、活锁

活锁出现在两个线程互相改变对方的结束条件,最后谁也无法结束。

@Slf4j(topic = "c.TestLiveLock")
public class TestLiveLock {
    static volatile int count = 10;
    static final Object lock = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            // 期望减到 0 退出循环
            while (count > 0) {
                sleep(0.2);
                count--;
                log.debug("count: {}", count);
            }
        }, "t1").start();
        new Thread(() -> {
            // 期望超过 20 退出循环
            while (count < 20) {
                sleep(0.2);
                count++;
                log.debug("count: {}", count);
            }
        }, "t2").start();
    }
}

六、饥饿

很多教程中把饥饿定义为,一个线程由于优先级太低,始终得不到 CPU 调度执行,又不能够结束,饥饿的情况不易演示,讲读写锁时会涉及饥饿问题。

下面我讲一下我遇到的一个线程饥饿的例子,先来看看使用顺序加锁的方式解决之前的死锁问题

 

顺序加锁可以解决死锁,但是容易造成饥饿。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目复习:基于TCP的文件服务器

ser.c(服务器): #include "./fun.h"int main(int argc,const char * argv[]) {//1.判断入参if(argc!3){fprintf(stderr,"入参为空&#xff0c;请检查\n");return -1;}//端口号转整型int portatoi(argv[2]);//变量声明struct sockaddr_in sin;int sinLensi…

axios.defaults.baseURL的三种配置方法

axios.defaults.baseURL的三种配置方法目录概述需求&#xff1a;设计思路实现思路分析1.少2.2.动态获取请求地址3.3.采用配置文件参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,m…

SEAL 0.3 正式发布:国内首个全链路软件供应链安全管理平台

12月1日&#xff0c;软件供应链安全管理平台 SEAL 0.3 正式发布&#xff08;以下简称“SEAL”&#xff09;&#xff0c;这是国内首个以全链路视角保护软件供应链的安全管理平台。两个月前 SEAL 0.2 发布&#xff0c;该版本创新性地提供了依赖项的全局汇总与关联&#xff0c;用户…

DSP篇--C6678功能调试系列之SPI调试

目录 1、初始化 2、数据传输 1、初始化 Perform the following procedure for initializing the SPI: 1. Reset the SPI by clearing the RESET bit in the SPI global control register 0 (SPIGCR0) to 0. 2. Take the SPI out of reset by setting SPIGCR0.RESET to 1. 3. …

【使用 BERT 的问答系统】第 6 章 :BERT 模型应用:其他任务

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

【大数据入门核心技术-Zookeeper】(三)Zookeeper的选举机制和流程

目录 一、Zookeeper的选举机制 1、每一个 Server 都会发出一个投票 2、接收来自各个 Server 的投票 3、处理投票 4、统计投票 5、改变服务器状态 二、Zookeeper的选举流程 一、Zookeeper的选举机制 Zookeeper 在配置文件中并没有指定 Master 和 Slave。但是&#xff0c;…

软件测试培训之十个无脚本测试方案

1.自然语言处理(NLP) 目前&#xff0c;一些最新的无脚本自动化测试工具能够通过采用NLP语法&#xff0c;来创建各种测试用例。就像编写简单的英语语句一样&#xff0c;用户可以轻松地实现测试用例的自动化。此类工具一般会带有AI驱动的内核&#xff0c;因此大幅节省了用户对其维…

【遥感图像融合:梯度指导:纹理细节】

GTP-PNet: A residual learning network based on gradient transformation prior for pansharpening &#xff08;一种基于梯度变换的剩余学习网络&#xff09; 提出了一种基于梯度变换先验的残差学习网络GTP-PNet&#xff0c;用于生成光谱分布准确、空间结构合理的高质量HRM…

车间生产设备管理有哪些问题?低代码来助力

随着科学技术对生产技术与生产工艺流程的不断改革创新&#xff0c;同时受市场变化的影响&#xff0c;企业生产管理模式也发生了巨大的改变&#xff0c;对车间生产设备管理的要求更高&#xff0c;并在一定层面推动了车间生产设备管理模式的创新和转变发展。但由于不同的企业面对…

JavaScript---DOM---DOM简介、获取元素、事件基础、操作元素---11.5

DOM简介 什么是DOM 文档对象模型&#xff08;Document Object Model&#xff0c;简称DOM&#xff09;是W3C组织推荐的处理可扩展标记语言&#xff08;HTML或者XML&#xff09;的标准编程接口。 W3C已经定义了一系列的DOM接口&#xff0c;通过这些DOM接口可以改变网页的内容、…

[附源码]计算机毕业设计springboot学生宿舍管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

如何在 Windows 10/8.1/8/7 上无密码删除 Deep Freeze

如何在 Windows 10/8.1/8/7 上无密码删除 Deep Freeze 有些人认真对待计算机安全问题。这些人会安装 Deep Freeze 冰点来保护他们的计算机。该应用程序的便利之处在于它会在重新启动时将计算机恢复到原始的预设配置。因此&#xff0c;可以轻松消除重启之间发生的任何变化&#…

海量数据如何在Web端实现动态可视化?看看这家企业是怎么做的

“我们TestLogger公司是一家赛车行业的软件公司&#xff0c;主要是通过分析在赛道上多个传感器收集到的赛车数据&#xff0c;帮助提高赛车性能。TestLogger Analyzer就是其中的一款核心数据分析工具&#xff0c;在我们构建该工具的第一个产品原型时&#xff0c;就发现由于不同类…

(附源码课件)10款Java小游戏满足你各种需求

游戏推荐 黄金矿工项目 飞机大战项目 超级玛丽项目 坦克大战项目 大鱼吃小鱼项目 飞翔的小鸟项目 扫雷项目 贪吃蛇项目 推箱子项目 本套视频课程包含&#xff1a; 1、王者荣耀项目 开发环境&#xff1a;jdk1.8 开发工具:eclipse JavaEE基础如下&#xff1a;变量、数据类型…

[附源码]计算机毕业设计springboot校友社交系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

uni-app入门:自定义tabbar

本文介绍如何使用vant Weapp定义自定义tabbar.按照自定义图标的方式进行添加: 自定义tabbar微信官方链接: https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html 1.导入vant weapp并构建npm 项目根目录右键选择外部终端窗口中打开 …

Numpy入门[2]——Matplotlib 基础

Numpy入门[2]——Matplotlib 基础 参考&#xff1a; https://ailearning.apachecn.org/ Python直接使用plot()函数画图 使用Jupyter进行练习 在使用Numpy之前&#xff0c;需要了解一些画图的基础。 Matplotlib是一个类似Matlab的工具包&#xff0c;主页地址为 http://matplot…

梁建章:旅行重回全球时代主题 构建“创新与传承”大场景

近日&#xff0c;在“防疫二十条”等最新措施基础上&#xff0c;国内多地宣布优化调整防疫措施&#xff0c;旅游市场复苏节奏也有望加速推进。 12月2日&#xff0c;携程集团在澳门举办“与时聚进”2022全球合作伙伴峰会。携程集团联合创始人、董事局主席梁建章&#xff0c;携程…

JS中常用的Date内置对象&处理Date内置对象的一些方法

JavaScript 中的对象分为3种&#xff1a;自定义对象 、内置对象、 浏览器对象 内置对象就是指 JS 语言自带的一些对象&#xff0c;这些对象供开发者使用&#xff0c;并提供了一些常用的或是最基本而必要的功能 JavaScript 提供了多个内置对象&#xff1a;Math、 Date 、Array…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java高校教师科研能力评定系统40n60

要对当前自己的学校对于计算机毕业设计的要求以及严格程度有所了解&#xff0c;这个主要是借助上一届已经毕业的学长学姐了解一下&#xff0c;但是有一点要注意的是&#xff0c;对于每一届毕业生的毕业设计的处理&#xff0c;学校都有很大的调整&#xff0c;这一点尤其重要。其…