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

三明网站建设百度关键词价格查询软件

三明网站建设,百度关键词价格查询软件,陕西疫情最新消息今天公布,国外设计师灵感网站死锁 在Java中使用多线程,就会有可能导致死锁问题。死锁会让程序一直卡住,程序不再往下执行。 我们只能通过中止并重启的方式来让程序重新执行。 这是我们非常不愿意看到的一种现象,我们要尽可能避免死锁的情况发生! 死锁的原因…

死锁

在Java中使用多线程,就会有可能导致死锁问题。死锁会让程序一直住,程序不再往下执行。

我们只能通过中止并重启的方式来让程序重新执行。
这是我们非常不愿意看到的一种现象,我们要尽可能避免死锁的情况发生!

死锁的原因:

  1. 当前线程拥有其他线程需要的资源
  2. 当前线程等待其他线程已拥有的资源
  3. 都不放弃自己拥有的资源
锁顺序死锁

线程1调用leftRight()方法,得到left锁
同时线程2调用rightLeft()方法,得到right锁线程1和线程2都继续执行,此时线程1需要right锁才能继续往下执行。此时线程2需要left锁才能继续往下执行。
线程1的left锁并没有释放,线程2的right锁也没有释放。
所以他们都只能等待,而这种等待是无期限的–>永久等待–>死锁

class Demo implements Runnable{private final Object left = new Object(); private final Object right = new Object();@Overridepublic void run() {leftRight();rightLeft();}public void leftRight() {synchronized (left) {System.out.println("线程" + Thread.currentThread().getName() + "拿到left,还需要right");synchronized (right) {System.out.println("线程" + Thread.currentThread().getName() + "拿到left和right");}}}public void rightLeft() {synchronized (right) {System.out.println("线程" + Thread.currentThread().getName() + "拿到right,还需要left");synchronized (left) {System.out.println("线程" + Thread.currentThread().getName() + "拿到right和left");}}}
}
动态锁顺序死锁

代码释义:获取源账户与目标账户,判断余额充足后进行加减操作。
死锁现象:线程1源账户a,目标账户b。线程2源账户b,目标账户a。

public class ThreadTest {public static void main(String[] args) {Test test = new Test();new Thread(test, "1").start();new Thread(test, "2").start();new Thread(test, "3").start();new Thread(test, "4").start();}
}class Test implements Runnable {Account a = new Account("A", 1000);Account b = new Account("B", 1000);@Overridepublic void run() {transferMoney(a, b, 100);transferMoney(b, a, 100);}public void transferMoney(Account fromAccount, Account toAccount, double money) {synchronized (fromAccount) {System.out.println("线程" + Thread.currentThread().getName() + "获得账户" + fromAccount.getName());synchronized (toAccount) {System.out.println("线程" + Thread.currentThread().getName() + "获得账户" + toAccount.getName());if (fromAccount.getMoney() < money) {System.out.println("余额不足");} else {fromAccount.setMoney(fromAccount.getMoney() - money);toAccount.setMoney(toAccount.getMoney() + money);System.out.println("转账后:" + fromAccount.getName() + "的余额:" +fromAccount.getMoney());System.out.println("转账后:" + toAccount.getName() + "的余额:" + toAccount.getMoney());}}}}
}
@Data
class Account {public Account(String name, double money) {this.name = name;this.money = money;}private String name;private double money;
}
协作对象之间发生死锁

getImage()setLocation(Point location)都需要获取两个锁,且在操作途中是没有释放锁的。

这就是隐式获取两个锁(对象之间协作)很容易造成死锁

public class CooperatingDeadlock {class Taxi {private Point location, destination;private final Dispatcher dispatcher;public Taxi(Dispatcher dispatcher) {this.dispatcher = dispatcher;}public synchronized Point getLocation() {return location;}// setLocation 需要Taxi内置锁public synchronized void setLocation(Point location) {this.location = location;if (location.equals(destination))// 调用notifyAvailable()需要Dispatcher内置锁dispatcher.notifyAvailable(this);}public synchronized Point getDestination() {return destination;}public synchronized void setDestination(Point destination) {this.destination = destination;}}class Dispatcher {private final Set<Taxi> taxis;private final Set<Taxi> availableTaxis;public Dispatcher() {taxis = new HashSet<Taxi>();availableTaxis = new HashSet<Taxi>();}public synchronized void notifyAvailable(Taxi taxi) {availableTaxis.add(taxi);}// 调用getImage()需要Dispatcher内置锁public synchronized Image getImage() {Image image = new Image();for (Taxi t : availableTaxis)// 调用getLocation()需要Taxi内置锁image.drawMarker(t.getLocation());return image;}}class Image {public void drawMarker(Point p) {}}
}

避免死锁的方法

避免死锁可以概括成三种方法:

  • 固定加锁的顺序(针对锁顺序死锁)
  • 开放调用(针对对象之间协作造成的死锁)
  • 使用定时锁–>tryLock()如果等待获取锁时间超时,则抛出异常而不是一直等待
固定锁顺序避免死锁

得到对应的hash值来固定加锁的顺序,这样不会出现死锁。

public class OrderLock {private static final Object tieLock = new Object();public void transferMoney(final Account fromAccount, final Account toAccount, final DollarAmount amount)throws InsufficientFundsException {class Helper {public void transfer() throws InsufficientFundsException {if (fromAccount.getBalance().compareTo(amount) < 0)throw new InsufficientFundsException();else {fromAccount.debit(amount);toAccount.credit(amount);}}}int fromHash = System.identityHashCode(fromAccount);int toHash = System.identityHashCode(toAccount);if (fromHash < toHash) {synchronized (fromAccount) {synchronized (toAccount) {new Helper().transfer();}}} else if (fromHash > toHash) {synchronized (toAccount) {synchronized (fromAccount) {new Helper().transfer();}}} else {synchronized (tieLock) {synchronized (fromAccount) {synchronized (toAccount) {new Helper().transfer();}}}}}
}
开放调用避免死锁

在协作对象之间发生死锁的例子中,主要是因为在调用某个方法时就需要持有锁,并且在方法内部也调用了其他带锁的方法。

如果在调用某个方法时不需要持有锁,那么这种调用被称为开放调用。同步代码块最好仅被用于保护那些涉及共享状态的操作

class CooperatingLock {@ThreadSafeclass Taxi {@GuardedBy("this")private Point location, destination;private final Dispatcher dispatcher;public Taxi(Dispatcher dispatcher) {this.dispatcher = dispatcher;}public synchronized Point getLocation() {return location;}public void setLocation(Point location) {boolean reachedDestination;synchronized (this) {this.location = location;reachedDestination = location.equals(destination);}if (reachedDestination)dispatcher.notifyAvailable(this);}public synchronized Point getDestination() {return destination;}public synchronized void setDestination(Point destination) {this.destination = destination;}}@ThreadSafeclass Dispatcher {@GuardedBy("this")private final Set<Taxi> taxis;@GuardedBy("this")private final Set<Taxi> availableTaxis;public Dispatcher() {taxis = new HashSet<Taxi>();availableTaxis = new HashSet<Taxi>();}public synchronized void notifyAvailable(Taxi taxi) {availableTaxis.add(taxi);}public Image getImage() {Set<Taxi> copy;synchronized (this) {copy = new HashSet<Taxi>(availableTaxis);}Image image = new Image();for (Taxi t : copy)image.drawMarker(t.getLocation());return image;}}class Image {public void drawMarker(Point p) {}}
}
使用定时锁

使用显式Lock锁,在获取锁时使用tryLock()方法。当等待超时的时候,tryLock()不会一直等待,而是返回错误信息。

使用tryLock()能够有效避免死锁问题。tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。

public class tryLock {public static void main(String[] args) {System.out.println("开始");final Lock lock = new ReentrantLock();new Thread() {@Overridepublic void run() {String tName = Thread.currentThread().getName();if (lock.tryLock()) {System.out.println(tName + "获取到锁!");} else {System.out.println(tName + "获取不到锁!");return;}try {for (int i = 0; i < 5; i++) {System.out.println(tName + ":" + i);}Thread.sleep(5000);} catch (Exception e) {System.out.println(tName + "出错了!!!");} finally {System.out.println(tName + "释放锁!!");lock.unlock();}}}.start();new Thread() {@Overridepublic void run() {String tName = Thread.currentThread().getName();if (lock.tryLock()) {System.out.println(tName + "获取到锁!");} else {System.out.println(tName + "获取不到锁!");return;}try {for (int i = 0; i < 5; i++) {System.out.println(tName + ":" + i);}} catch (Exception e) {System.out.println(tName + "出错了!!!");} finally {System.out.println(tName + "释放锁!!");lock.unlock();}}}.start();System.out.println("结束");}
}

总结

发生死锁的原因主要由于:

  • 线程之间交错执行

    解决:以固定的顺序加锁

  • 执行某方法时就需要持有锁,且不释放

    解决:缩减同步代码块范围,最好仅操作共享变量时才加锁

  • 永久等待

    解决:使用tryLock()定时锁,超时则返回错误信息

http://www.shuangfujiaoyu.com/news/33162.html

相关文章:

  • 专业网站建设知识百度账号申诉
  • 烟台网站排名优化价格百度一下了你就知道官网
  • 做网站手机版和电脑版怎么区分南昌百度网站快速排名
  • 网络服务商在哪黑帽seo技巧
  • wordpress模板标签西安分类信息seo公司
  • 网站站长seo推广上海优化公司排行榜
  • 如何在网站做投票公司网站制作费用
  • 工业园企业建设网站公司宝塔没有域名直接做网站怎么弄
  • 网络营销案例小故事分享seo优化人员
  • 做论坛网站需要备案贵州二级站seo整站优化排名
  • 打开建设银行官方网站首页常州谷歌推广
  • 如何做网站地图txt我在百度下的订单如何查询
  • 国外访问国内网站速度网站排名优化教程
  • 美国有网站建设公司吗网络营销策划师
  • 哪些是+joomla做的网站营销知识和技巧
  • 免费个人网站2018网站广告投放价格表
  • 请人建网站应注意什么关键词优化公司排名
  • 公司做完网站怎么搜不到dw友情链接怎么设置
  • 嘉陵区建设局网站百度seo搜索引擎优化
  • 上海市装修公司百度seo
  • 注册了域名之后怎么做网站郑州网络推广哪个好
  • 石家庄最新一例轨迹企业seo优化服务
  • 关于政府网站建设的调研报告培训网页
  • 速升网站黄页网络的推广网站有哪些类型
  • 程序员做兼职的网站大一html网页制作作业
  • 超酷网站湖南疫情最新消息今天
  • 我买了一个域名怎么做网站怎么寻找网站关键词并优化
  • 汽车类网站设计规划优化算法
  • 外链都没有的网站如何做排名的百度app免费下载安装
  • 想把自己做的网站放到网上如何制作网页链接