线程活跃性

文章目录

    • 1. 简介
    • 2. 死锁
    • 3. 活锁
    • 4. 饥饿

1. 简介

所谓线程的活跃性,我们知道每个线程所要执行的java代码是有限的,在执行一段时间后线程自然会陷入Terminated状态,但由于某些外部原因导致线程一直执行不完,一直处于活跃状态,这就是所谓的线程的活跃性。下面一一介绍导致线程活跃性的情况:

2. 死锁

有这么一种情况,一个线程同时获取多把锁,这时就容易发生死锁:

t1线程获得A对象锁,接下来想获取B对象的锁,t2线程获取B对象的锁,而想要获得A对象的锁。这就是一种死锁情况。

如下面代码就模拟了死锁的情况


@Slf4j
public class Hello{
	
	public static void main(String[] args){
	    test();
	}

	public static void test(){
		Object A=new Object();
		Object B=new Object();
		new Thread(()->{
			synchronized (A){
				try {
					Thread.sleep(1000);
					log.debug("我已经有了锁A,现在想获取锁B");
					synchronized (B){
						log.debug("我已经有了锁A,且获取了锁B");
					}
				} catch (InterruptedException e) {
					throw new RuntimeException(e);
				}
			}
		},"线程1").start();
		new Thread(()->{
			synchronized (B){
				try {
					Thread.sleep(1000);
					log.debug("我已经有了锁B,现在想获取锁A");
					synchronized (A){
						log.debug("我已经有了锁B,且获取了锁A");
					}
				} catch (InterruptedException e) {
					throw new RuntimeException(e);
				}
			}
		},"线程2").start();
	}
}

发生了死锁我们此时就可以使用死锁一些工具来定位到死锁发生的地方。检测死锁可以使用jconsole工具,或者使用.jps定位进程id,再用jstack定位死锁。

  1. 获取进程ID

在这里插入图片描述

  1. 查看线程状态
jstack 1757

可以发现已经出现了死锁信息

在这里插入图片描述
在这里插入图片描述

我们同样可以使用jconsole

jconsole

在这里插入图片描述

在死锁中有一个著名的问题叫做哲学家就餐问题:

在这里插入图片描述
当五个哲学家都拿一根筷子就出现了死锁问题。

筷子类:

final class Chopsticks{
     String name;
	 public chopsticks(String name){
		 this.name=name;
	 }

	@Override
	public String toString() {
		return "chopsticks{" +
				"name='" + name + '\'' +
				'}';
	}
}

哲学家类:

@Slf4j
final class Philosopher extends Thread{
	Chopsticks left;
	Chopsticks right;

	@Override
	public void run() {
		while(true){
			synchronized (left){
				synchronized (right){
					try {
						eat();
					} catch (InterruptedException e) {
						throw new RuntimeException(e);
					}
				}
			}
		}
	}

	public void eat() throws InterruptedException {
		log.debug("两只筷子都有了,开始吃了");
		Thread.sleep(1000);
	}
	public Philosopher(Chopsticks left, Chopsticks right,String name){
		super(name);
		this.left=left;;
		this.right=right;


	}

}

测试代码:

@Slf4j
public class Hello{
	
	public static void main(String[] args){
         Chopsticks c1=new Chopsticks("筷子1");
		 Chopsticks c2=new Chopsticks("筷子2");
		 Chopsticks c3=new Chopsticks("筷子3");
		 Chopsticks c4=new Chopsticks("筷子4");
		 Chopsticks c5=new Chopsticks("筷子5");
		 new Philosopher(c1,c2,"哲学家1").start();
		 new Philosopher(c2,c3,"哲学家2").start();
		 new Philosopher(c3,c4,"哲学家3").start();
		 new Philosopher(c4,c5,"哲学家4").start();
		 new Philosopher(c5,c1,"哲学家5").start();
	}


}

jconsole检测死锁:

在这里插入图片描述
使用java地可重入锁可以解决该问题

3. 活锁

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

@Slf4j
public class Hello{
	static volatile int count=10;
	static final Object lock=new Object();
	public static void main(String[] args){
		new Thread(()->{
			while(count>0){
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					throw new RuntimeException(e);
				}
				count--;
				log.debug("count:{}",count);
			}
		},"t1").start();
		new Thread(()->{
			while(count>0){
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					throw new RuntimeException(e);
				}
				count++;
				log.debug("count:{}",count);
			}
		},"t2").start();
	}
}

解决方法,让两个线程执行错开

4. 饥饿

饥饿指的是,一个线程由于优先级太低,始终得不到CPU的调度执行,也不能够结束。

在这里插入图片描述
回到上面哲学家问题,我们发现哲学家1-4都是顺序获取锁的,到哲学加5是先获取5再获取1,所以他不是按顺序获取的,这里我们改一下代码:

new Philosopher(c1,c5,"哲学家5").start();

在这里插入图片描述
此时就不会出现死锁了,但我们发现哲学家5一直没有获取锁,说明它发生了饥饿。

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

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

相关文章

leetCode 493 翻转对 归并分治 + 图解

493. 翻转对 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums &#xff0c;如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。你需要返回给定数组中的重要翻转对的数量。 求"小和"问题是&#xff0c;当我 j 来到一个位置的…

快速排序实现方法(剑指offer思路)

快速排序思想 从参与排序的数组中&#xff0c;选择一个数&#xff0c;把小于这个数的放在左边&#xff0c;大于这个数的放在右边&#xff0c;然后递归操作。 实现算法思路 选择最后一个当作参考值&#xff0c;使用small索引当作比这个数小的下标值遍历数组&#xff0c;如果小…

【Python】 Python 使用 Pillow 处理图像:几何变换

Python 使用 Pillow 处理图像&#xff1a;几何变换 pillow库操作切片、旋转、滤镜、输出文字、调色板等功能一应俱全。 1. 几何变换 Image 包含调整图像大小 resize() 和旋转 rotate() 的方法。前者采用元组给出新的大小&#xff0c;后者采用逆时针方向的角度。 调整大小并…

n-gram语言模型——文本生成源码

n-gram语言模型——文本生成源码 n-gram模型的基本原理 文本生成的步骤 1. 准备和分词 2. 构建n-gram模型 3. 平滑技术的应用 4. 生成文本 源码 在自然语言处理的领域中&#xff0c;n-gram语言模型是一种基础而强大的工具。它通过考虑词汇的序列来预测文本内容&#xff…

MXNet中图解稀疏矩阵(Sparse Matrix)的压缩与还原

1、概述 对于稀疏矩阵的解释&#xff0c;就是当矩阵里面零元素远远多于非零元素&#xff0c;且非零元素没有规律&#xff0c;这样的矩阵就叫做稀疏矩阵&#xff0c;反过来就是稠密矩阵&#xff0c;其中非零元素的数量与所有元素的比值叫做稠密度&#xff0c;一般稠密度小于0.0…

Python开发运维:Python3.7使用QQ邮箱发送不同类型邮件

目录 一、理论 1.邮件发送 二、实验 1.Python3.7使用QQ邮箱发送普通邮件 2.Python3.7使用QQ邮箱发送包含图片与附件的邮件 三、问题 1.Pycharm中如何放大和缩小代码界面 一、理论 1.邮件发送 &#xff08;1&#xff09;概念 SMTP&#xff08;Simple Mail Transfer Pro…

Linux AMH 服务器管理面板远程访问

文章目录 1. 前言2. Linux 安装AMH 面板3. 本地访问AMH 面板4. Linux安装Cpolar5. 配置AMH面板公网地址6. 远程访问AMH面板7. 固定AMH面板公网地址8、结语 1. 前言 AMH 是一款基于 Linux 系统的服务器管理面板&#xff0c;它提供了一系列的功能&#xff0c;包括网站管理、FTP …

Linux-用户与用户组,权限

1.用户组管理&#xff08;以下命令需root用户执行&#xff09; ①创建用户组 groupadd 用户组名 ②删除用户组 groupdel 用户组名 2.用户管理&#xff08;以下命令需root用户执行&#xff09; ①创建用户 useradd [-g -d] 用户名 >-g&#xff1a;指定用户的组&#xff0c;不…

颠覆人工智能计算硬件的新计算技术

颠覆人工智能计算硬件的新计算技术 图纸解释说明参考网址加法器模拟解析图纸 解释说明 简单的介绍 使用一个小的llm 模拟 计算最小单元加法器 等硬件 在使用 简单的 电阻矩阵模拟矩阵计算 固化llm 参数代替 半导体硬件 而后组成 大规模人工智能计算 参考网址 加法器 但是直接…

TCP与UDP

文章目录 TCP与UDP传输层的作用端口号UDPTCPUDP首部的格式TCP首部格式 TCP与UDP TCP/IP中有两个具有代表性的传输层协议&#xff0c;它们分别是TCP和UDP。TCP提供可靠的通信传输&#xff0c;而UDP则常被用于让广播和细节控制交给应用的通信传输。总之&#xff0c;根据通信的具…

win10使用mingw安装OpenCV4.8

1. cmake安装 下载链接如下https://github.com/Kitware/CMake/releases/download/v3.27.7/cmake-3.27.7-windows-x86_64.zip 解压后放到指定目录后&#xff0c;添加bin目录到环境变量即可。 2. mingw安装 下载链接如下(下图的x86_64-posix-sjlj)&#xff1a; Download x86_…

mybatis的简单教程

整体就是mysql里存了一张表&#xff0c;然后在java程序里用mybatis把数据读出来的一个简单示例。 库 blog里有一张表 article 整个项目就是增加了这3个文件 首先是mybatis-config.xml文件 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE c…

【操作系统内核】线程

【操作系统内核】线程 为什么需要线程 比如我要做一个视频播放器&#xff0c;就需要实现三个功能&#xff1a; ① 从磁盘读取视频数据 ② 对读取到的视频数据进行解码 ③ 对解码的数据进行播放 如果串行执行&#xff08;通过一个进程来执行&#xff09;&#xff1a; 那么…

【MySQL】rank()、row_number()、dense_rank()用法详解

建表测试 测试表数据&#xff1a;test1 CREATE DATABASE /*!32312 IF NOT EXISTS*/db_test /*!40100 DEFAULT CHARACTER SET utf8 */; USE db_test; /*Table structure for table test1 */ DROP TABLE IF EXISTS test1; CREATE TABLE test1 ( id int(10) NOT NULL, score i…

数据结构从未如此简单——图(一)

文章目录 前言图的初印象教科书力扣工作中的实际应用我们的学习方法 前言 个人感觉数据结构学习最大的难点就是抽象。这些概念和算法都是从许多源问题中抽离、精炼、总结出来的。我们学习的看似是最精华的部分&#xff0c;但是忽略了推导过程&#xff0c;很容易变成死记硬背&a…

C语言求解有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?

完整代码&#xff1a; /*有一对兔子&#xff0c;从出生后第3个月起每个月都生一对兔子&#xff0c;小兔子长到第三个月后每个月 又生一对兔子&#xff0c;假如兔子都不死&#xff0c;问每个月的兔子总数为多少&#xff1f; 程序分析&#xff1a; 兔子的规律为数列1,1,2,3,5,8…

MySQL中的json使用注意

MySQL中json是一种重要的数据类型 好的点在于其不必事先定义列得名称啥的 不过不要将明显的关系型数据作为json来存储&#xff0c;例如用户余额、姓名、身份证等&#xff0c;这些是用户必须包含的数据 json适合存储的是给每个用户&#xff08;或者物品&#xff09;打的标签&…

超简单的Linux FTP服务搭建教程

目录 前言1、检查vsftp是否已安装2、安装vsftpd3、启动ftp服务4、测试ftp服务5、上传文件配置总结 前言 本文记录了在Kylin Linux Desktop V10(SP1)系统上搭建FTP服务的过程。FTP是File Transfer Protocol的缩写&#xff0c;译为文件传输协议&#xff0c;是用于在网络上进行文…

docker复制镜像文件

一、复制镜像 #1. 查找本机已有的镜像docker images |grep xxxx#2. 将镜像复制出来指向到xxxx.tar的文件中 docker save 343cca04e31d > xxxx.tareg: 二、加载镜像 直接将拷贝好的镜像包直接加载即可 docker load < myimage.tar

NO.304 二维区域和检索 - 矩阵不可变

题目 给定一个二维矩阵 matrix&#xff0c;以下类型的多个请求&#xff1a; 计算其子矩形范围内元素的总和&#xff0c;该子矩阵的 左上角 为 (row1, col1) &#xff0c;右下角 为 (row2, col2) 。 实现 NumMatrix 类&#xff1a; NumMatrix(int[][] matrix) 给定整数矩阵 …
最新文章