当两个或两个以上的线程在执行过程中,因为争夺资源而造成的一种相互等待的状态,由于存在一种环路的锁依赖关系而永远地等待下去,如果没有外部干涉,他们将永远等待下去,此时的这个状态称之为死锁。
经典的 "哲学家进餐" 问题很好地描述了死锁状况:
5个哲学家去吃中餐,坐在一张圆桌旁,他们有5根筷子(而不是5双),并且每两个人中间
放一根筷子,哲学家们要么在思考,要么在进餐,每个人都需要一双筷子才能吃到东西,并在吃
完后将筷子放回原处继续思考,有些筷子管理算法(1)能够使每个人都能相对及时的吃到东西,但
有些算法却可能导致一些或者所有哲学家都"饿死",后一种情况将产生死锁:每个人都拥有其他
人需要的资源,同时有等待其他人已经拥有的资源,并且每个人在获取所有需要的资源之前都不
会放弃已经拥有的资源。筷子管理算法(1):一个饥饿的科学家会尝试获得两根临近的筷子,但如果其中一根正在被另一个科学家使用,那么他将放弃已经得到的那根筷子,并在等待几分钟之后尝试
死锁:每个人都立即抓住自己左边的筷子,然后等待自己右边的筷子空出来,但同时又不放下已经拿到的筷子,形成一种相互等待的状态。饥饿:哲学家们都同时想吃饭,同时拿起左手边筷子,但是发现右边没有筷子,于是哲学家又同时放下左手边筷子,然后大家发现又有筷子了,又同时开始拿起左手边筷子,又同时放下,然后反复进行。
在线程A持有锁L并想获得锁M的同时,线程B持有锁M并尝试获得锁L,那么这两个线程将永远地等待下去,这种情况就是死锁形式(或者称为"抱死")
/**
* 死锁类示例
*/
public class DeadLock implements Runnable {
public int flag = 1;
//静态对象是类的所有对象共享的
private static Object o1 = new Object(), o2 = new Object();
@Override
public void run() {
System.out.println("flag:{}"+flag);
if (flag == 1) { //先锁o1,再对o2加锁,环路等待条件
synchronized (o1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o2) {
System.out.println("1");
}
}
}
if (flag == 0) {//先锁o2,在锁01
synchronized (o2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o1) {
System.out.println("0");
}
}
}
}
public static void main(String[] args) {
DeadLock td1 = new DeadLock();
DeadLock td2 = new DeadLock();
td1.flag = 1;
td2.flag = 0;
//td1,td2都处于可执行状态,但JVM线程调度先执行哪个线程是不确定的。
//td2的run()可能在td1的run()之前运行
new Thread(td1).start();
new Thread(td2).start();
}
}
1、当DeadLock 类的对象flag=1时(td1),先锁定o1,睡眠500毫秒2、而td1在睡眠的时候另一个flag==0的对象(td2)线程启动,先锁定o2,睡眠500毫秒3、td1睡眠结束后需要锁定o2才能继续执行,而此时o2已被td2锁定;4、td2睡眠结束后需要锁定o1才能继续执行,而此时o1已被td1锁定;5、td1、td2相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。
// 资金转账到账号
public static void transferMoney(Account fromAccount,
Account toAccount,
DollarAmount amount)
throws InsufficientFundsException {
// 锁定汇款者的账户
synchronized (fromAccount) {
// 锁定到账者的账户
synchronized (toAccount) {
// 判断账户的余额不能为负数
if (fromAccount.getBalance().compareTo(amount) < 0) {
throw new InsufficientFundsException();
} else {
// 汇款者的账户减钱
fromAccount.debit(amount);
// 到账者的账户增钱
toAccount.credit(amount);
}
}
}
}
上面的代码看起来都是按照相同的顺序来获得锁的,按道理来说是没有问题,但是上述代码中上锁的顺序取决于传递给``的参数顺序,而这些参数顺序又取决于外部的输入
transferMoney()
transferMoney(myAccount,yourAccount,10)
;transferMoney(yourAccount,myAccount,20)
;当一组java线程发生死锁的时候,那么这些线程永远不能再使用了,根据线程完成工作的不同,可能会造成应用程序的完全停止,或者某个特定的子系统不能再使用了,或者是性能降低,这个时候恢复应用程序的唯一方式就是中止并重启它,死锁造成的影响很少会立即显现出来,如果一个类发生死锁,并不意味着每次都会发生死锁,而只是表示有可能,当死锁出现的时候,往往是在最糟糕的时候——在高负载的情况下。
如果两个线程(A和B),当A线程已经锁住了Z,而又去尝试锁住X,而X已经被线程B锁住,线程A和线程B分别持有对应的锁,而又去争夺其他一个锁(尝试锁住另一个线程已经锁住的锁)的时候,就会发生死锁,如下图:
两个线程试图以不同的顺序来获得相同的锁,如果按照相同的顺序来请求锁,那么就不会出现循环的加锁依赖性,因此也就不会产生死锁,每个需要锁Z和锁X的线程都以相同的顺序来获取Z和X,那么就不会发生死锁了,如下图所示:
这样死锁就永远不会发生。针对两个特定的锁,可以尝试按照锁对象的hashCode值大小的顺序,分别获得两个锁,这样锁总是会以特定的顺序获得锁,我们通过设置锁的顺序,来防止死锁的发生,在这里我们使用``方法来定义锁的顺序,这个方法将返回由Obejct.hashCode 返回的值,这样就可以消除死锁发生的可能性。
public class DeadLockExample3 {
// 加时赛锁,在极少数情况下,如果两个hash值相等,使用这个锁进行加锁
private static final Object tieLock = new Object();
public void transferMoney(final Account fromAcct,
final Account toAcct,
final DollarAmount amount)
throws InsufficientFundsException {
class Helper {
public void transfer() throws InsufficientFundsException {
if (fromAcct.getBalance().compareTo(amount) < 0)
throw new InsufficientFundsException();
else {
fromAcct.debit(amount);
toAcct.credit(amount);
}
}
}
// 得到两个锁的hash值
int fromHash = System.identityHashCode(fromAcct);
int toHash = System.identityHashCode(toAcct);
// 根据hash值判断锁顺序,决定锁的顺序
if (fromHash < toHash) {
synchronized (fromAcct) {
synchronized (toAcct) {
new Helper().transfer();
}
}
} else if (fromHash > toHash) {
synchronized (toAcct) {
synchronized (fromAcct) {
new Helper().transfer();
}
}
} else{ // 如果两个对象的hash相等,通过tieLock来决定加锁的顺序,否则又会重新引入死锁——加时赛锁
synchronized (tieLock) {
synchronized (fromAcct) {
synchronized (toAcct) {
new Helper().transfer();
}
}
}
}
}
}
有一项技术可以检测死锁和从死锁中恢复过来,就是使用Lock类中的定时``会返回一个失败信息,如果超时时限比获取锁的时间要长很多,那么就可以在发生某个意外后重新获得控制权。如下图所示:
死锁防止方法能够防止发生死锁,但必然会降低系统并发性,导致低效的资源利用率,其中最具有代表性的避免死锁算法是银行家算法。
1、多个资源的银行家算法
上图中有五个进程,四个资源。左边的图表示已经分配的资源,右边的图表示还需要分配的资源。最右边的 E、P 以及 A 分别表示:总资源、已分配资源以及可用资源,注意这三个为向量,而不是具体数值,例如 A=(1020),表示 4 个资源分别还剩下 1/0/2/0。
检查一个状态是否安全的算法如下:
Jconsole是JDK自带的监控工具,在JDK/bin目录下可以找到。它用于连接正在运行的本地或者远程的JVM,对运行在Java应用程序的资源消耗和性能进行监控,并画出大量的图表,提供强大的可视化界面。而且本身占用的服务器内存很小,甚至可以说几乎不消耗。
1、撤销陷入死锁的所有进程,解除死锁,继续运行。
2、逐个撤销陷入死锁的进程,回收其资源并重新分配,直至死锁解除。
可选择符合下面条件之一的先撤销:
1.CPU消耗时间最少者
2.产生的输出量最小者
3.预计剩余执行时间最长者
4.分得的资源数量最少者后优先级最低者
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。