当前位置: 首页 > news >正文

设计商城网站 优帮云什么是淘宝seo

设计商城网站 优帮云,什么是淘宝seo,wordpress 对外请求,杭州专业做网站的公司有哪些死锁,一组互相竞争的资源的线程之间相互等待,导致永久阻塞的现象。 如下图所示: 与死锁对应的,还有活锁,是指线程没有出现阻塞,但是无限循环。 有一个经典的银行转账例子如下: 我们有个账户类…

死锁,一组互相竞争的资源的线程之间相互等待,导致永久阻塞的现象。

如下图所示:
在这里插入图片描述
与死锁对应的,还有活锁,是指线程没有出现阻塞,但是无限循环。


有一个经典的银行转账例子如下:

我们有个账户类,其中有两个属性:账户名和余额。
它有两个方法:转入、转出。

public class Account {private String countName;private int balance;public Account(String countName, int balance) {this.countName = countName;this.balance = balance;}/*** 转出金额,更新转出方余额,金额减少* @param amount*/public void debit(int amount){this.balance -= amount;}/*** 存入金额,更新转入方余额,金额增多* @param amount*/public void credit(int amount){this.balance += amount;}public String getCountName() {return countName;}public void setCountName(String countName) {this.countName = countName;}public int getBalance() {return balance;}public void setBalance(int balance) {this.balance = balance;}
}

还有一个转账操作类,它有三个属性:转入账户、转出账户、转账金额。
它实现了Runnable接口,run方法中是转账逻辑代码。
我们使用 while(true) 让他不停的进行转账操作:如果账户余额大于转账金额,就让转出账号减少amount,转入账户增加amount。打印出线程名、金额转移方向、以及每个账户余额。
我们在main方法中进行测试,创建两个转账账户,使用两个线程操作这两个账户,让他们相互转账。

public class TransferAccount implements Runnable{private Account fromAccount;private Account toAccount;private int amount;public TransferAccount(Account fromAccount, Account toAccount, int amount) {this.fromAccount = fromAccount;this.toAccount = toAccount;this.amount = amount;}@Overridepublic void run() {while(true){synchronized (fromAccount){synchronized (toAccount){if(fromAccount.getBalance()>=amount) {fromAccount.debit(amount);toAccount.credit(amount);}System.out.println(Thread.currentThread().getName());System.out.println(fromAccount.getCountName()+"->"+toAccount.getCountName()+":"+amount );System.out.println(fromAccount.getCountName() +"账户余额:"+ fromAccount.getBalance());System.out.println(toAccount.getCountName() +"账户余额:"+ toAccount.getBalance());}}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {Account bigHead = new Account("冤大头",100000);Account smallKill = new Account("门小抠",200000);new Thread(new TransferAccount(bigHead,smallKill,10)).start();new Thread(new TransferAccount(smallKill,bigHead,20)).start();}}

执行main方法后的输出结果:

Thread-0
冤大头->门小抠:10
冤大头账户余额:99990
门小抠账户余额:200010
Thread-1
门小抠->冤大头:20
门小抠账户余额:199990
冤大头账户余额:100010
Thread-1
门小抠->冤大头:20
门小抠账户余额:199970
冤大头账户余额:100030
Thread-0
冤大头->门小抠:10
冤大头账户余额:100020
门小抠账户余额:199980
Thread-0
冤大头->门小抠:10
冤大头账户余额:100010
门小抠账户余额:199990
Thread-1
门小抠->冤大头:20
门小抠账户余额:199970
冤大头账户余额:100030
Thread-0
冤大头->门小抠:10
冤大头账户余额:100020
门小抠账户余额:199980
Thread-1
门小抠->冤大头:20
门小抠账户余额:199960
冤大头账户余额:100040
Thread-0
冤大头->门小抠:10
冤大头账户余额:100030
门小抠账户余额:199970
Thread-1
门小抠->冤大头:20
门小抠账户余额:199950
冤大头账户余额:100050
Thread-0
冤大头->门小抠:10
冤大头账户余额:100040
门小抠账户余额:199960
Thread-1
门小抠->冤大头:20
门小抠账户余额:199940
冤大头账户余额:100060

这时,我们发现进程还在运行,但是控台停止输出了,它停在那里了。
截图如下:
在这里插入图片描述

这时我们使用 jps 来查看一下java进程:

D:\open_source\MyBatis\MyThread\target\classes\demo>jps
23600
24676 Launcher
40244 Jps
23672 TransferAccount

然后输入 使用jstack来看详情:

D:\open_source\MyBatis\MyThread\target\classes\demo>jstack 23672
2023-02-26 18:37:57
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.351-b10 mixed mode):"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x000001b4fc785800 nid=0x6530 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Thread-1" #13 prio=5 os_prio=0 tid=0x000001b4fc77f800 nid=0x887c waiting for monitor entry [0x000000467adff000]java.lang.Thread.State: BLOCKED (on object monitor)at deadlock.TransferAccount.run(TransferAccount.java:20)- waiting to lock <0x000000076c5a4610> (a deadlock.Account)- locked <0x000000076c5a4658> (a deadlock.Account)at java.lang.Thread.run(Thread.java:750)"Thread-0" #12 prio=5 os_prio=0 tid=0x000001b4fc77c800 nid=0x8c80 waiting for monitor entry [0x000000467acff000]java.lang.Thread.State: BLOCKED (on object monitor)at deadlock.TransferAccount.run(TransferAccount.java:20)- waiting to lock <0x000000076c5a4658> (a deadlock.Account)- locked <0x000000076c5a4610> (a deadlock.Account)at java.lang.Thread.run(Thread.java:750)......Found one Java-level deadlock:
=============================
"Thread-1":waiting to lock monitor 0x000001b4fa208eb8 (object 0x000000076c5a4610, a deadlock.Account),which is held by "Thread-0"
"Thread-0":waiting to lock monitor 0x000001b4fa208e08 (object 0x000000076c5a4658, a deadlock.Account),which is held by "Thread-1"Java stack information for the threads listed above:
===================================================
"Thread-1":at deadlock.TransferAccount.run(TransferAccount.java:20)- waiting to lock <0x000000076c5a4610> (a deadlock.Account)- locked <0x000000076c5a4658> (a deadlock.Account)at java.lang.Thread.run(Thread.java:750)
"Thread-0":at deadlock.TransferAccount.run(TransferAccount.java:20)- waiting to lock <0x000000076c5a4658> (a deadlock.Account)- locked <0x000000076c5a4610> (a deadlock.Account)at java.lang.Thread.run(Thread.java:750)Found 1 deadlock.

我们可以看到,其中Thread-0和Thread-1都已经处于BLOCK状态,发生了死锁。


导致死锁发生,必须同时满足四个条件:互斥、占有且等待、不可抢占、循环等待。

  • 互斥:共享资源A和B只能被一个线程占用。
  • 占有且等待:线程Thread-1 已经取得共享资源X,在等待共享资源Y的时候,不释放共享资源X。
  • 不可抢占:其他线程不能强行抢占线程Thread-1 占有的资源。
  • 循环等待:线程Thread-1 等待线程Thread-2 占有的资源,线程Thread-2等待Thread-1 占有的资源。

如何解决?

如果要解决死锁问题,只需要破坏其中一个条件,使其不满足即可。
除了互斥(多线程的基础)之外,其他三个条件都可以考虑破坏。
实际中遇到死锁,只能重启,如果还是死锁,要定位问题点,然后修复代码(破坏掉死锁必须满足的条件之一)后重新发布。


我们来尝试破坏占有且等待的方式来破坏死锁:
新增加一个分配的类:Allocator,它有一个账户池。每个转账线程中要判断,账户池中是否已有此账户,如果没有可以转账,有的话就不转账。就可以避免共享资源同时存在于两个线程。

import java.util.ArrayList;
import java.util.List;public class Allocator {private List<Object> list = new ArrayList<>();synchronized boolean apply(Object fromAccount,Object toAccount){if(list.contains(fromAccount)||list.contains(toAccount)){return false;}list.add(fromAccount);list.add(toAccount);return true;}synchronized void free(Object fromAccount,Object toAccount){list.remove(fromAccount);list.remove(toAccount);}
}//相应的,TransAcount也要做修改:
public class TransferAccount implements Runnable {private Account fromAccount;private Account toAccount;private int amount;private Allocator allocator;public TransferAccount(Account fromAccount, Account toAccount, int amount, Allocator allocator) {this.fromAccount = fromAccount;this.toAccount = toAccount;this.amount = amount;this.allocator = allocator;}@Overridepublic void run() {while (true) {//判断账户是否已经分配过if (allocator.apply(fromAccount, toAccount)) {try {synchronized (fromAccount) {synchronized (toAccount) {if (fromAccount.getBalance() >= amount) {fromAccount.debit(amount);toAccount.credit(amount);}System.out.println(Thread.currentThread().getName());System.out.println(fromAccount.getCountName() + "->" + toAccount.getCountName() + ":" + amount);System.out.println(fromAccount.getCountName() + "账户余额:" + fromAccount.getBalance());System.out.println(toAccount.getCountName() + "账户余额:" + toAccount.getBalance());}}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}finally {allocator.free(fromAccount,toAccount);}}}}public static void main(String[] args) {Account bigHead = new Account("冤大头", 100000);Account smallKill = new Account("门小抠", 200000);Allocator allocator = new Allocator();new Thread(new TransferAccount(bigHead, smallKill, 10, allocator)).start();new Thread(new TransferAccount(smallKill, bigHead, 20, allocator)).start();}}

我们来避免第三个条件:使用Lock来替换掉 Synchronized。
Synchronized加锁后,要等到资源释放,而且锁是不可抢占的。
Lock中有个方法 tryLock,可以返回布尔值,如果返回fasle就不会进去。tryLock不会持续持有锁。

public class TransferAccount2 implements Runnable{private Account fromAccount;private Account toAccount;private int amount;private Lock fromAccountLock = new ReentrantLock();private Lock toAccountLock = new ReentrantLock();public TransferAccount2(Account fromAccount, Account toAccount, int amount) {this.fromAccount = fromAccount;this.toAccount = toAccount;this.amount = amount;}@Overridepublic void run() {while(true){//synchronized (fromAccount){if(fromAccountLock.tryLock()){if(toAccountLock.tryLock()){if(fromAccount.getBalance()>=amount) {fromAccount.debit(amount);toAccount.credit(amount);}System.out.println(Thread.currentThread().getName());System.out.println(fromAccount.getCountName()+"->"+toAccount.getCountName()+":"+amount );System.out.println(fromAccount.getCountName() +"账户余额:"+ fromAccount.getBalance());System.out.println(toAccount.getCountName() +"账户余额:"+ toAccount.getBalance());}}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {Account bigHead = new Account("冤大头",100000);Account smallKill = new Account("门小抠",200000);new Thread(new TransferAccount2(bigHead,smallKill,10)).start();new Thread(new TransferAccount2(smallKill,bigHead,20)).start();}}

http://www.hkea.cn/news/474456/

相关文章:

  • 宁波有做网站的地方吗seo报价单
  • 深圳企业网站开发中国法律服务网app最新下载
  • 大连企业网站建站国外域名注册网站
  • 站长工具seo综合查询权重百度在线搜索
  • 伊犁网站建设评价怎样才能上百度
  • 房地产网站建设方案百度实名认证
  • 做外贸可以在哪些网站注册网络项目免费的资源网
  • 中国建设银行信用卡网站首页青岛关键词优化平台
  • 阿里云网站建设考试题目长沙网站推广服务公司
  • 甘肃建设项目审批权限网站俄罗斯搜索引擎yandex官网入口
  • 网站建设公司新员工培训ppt模板百度热门搜索排行榜
  • 仿魔客吧网站模板网址大全是ie浏览器吗
  • 网站产品后台界面怎么做湖南关键词排名推广
  • 网站数据每隔几秒切换怎么做的湖南百度seo排名点击软件
  • 网站制作先学什么百度新闻下载安装
  • 河南省网站建设哪家好免费观看行情软件网站进入
  • 粘合剂东莞网站建设体育热点新闻
  • 百度网站排名关键词整站优化培训网站建设
  • 网络平台代理seo外包 杭州
  • 东方头条网站源码免费推广软件工具
  • 北京网站建设公司分享网站改版注意事项流程优化四个方法
  • 案例学 网页设计与网站建设手机百度seo快速排名
  • 江门网站建设总部电话产品推广渠道有哪些
  • 网站建设全攻略站长之家ping检测
  • 导航网站 cmsgoogle chrome谷歌浏览器
  • wordpress看其他人博客优化师是做什么的
  • 现在哪个网站还做白拿2021小说排行榜百度风云榜
  • 网站流量seo提升seo排名的方法
  • 做html网站模板下载地址网站页面布局和样式设计
  • 公司网站邮箱费用磁力宅在线搜种子