<b>对J2EE中死锁问题的研究</b>[Java编程]
本文“<b>对J2EE中死锁问题的研究</b>[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
大大都重要的利用程序都触及高度并发性和多个抽象层.并发性与资源争用有关,并且是招致死锁问题增添的因素之一.多个抽象层使断绝并修复死锁环境的工作变得越发艰难.
普通,当同时履行两个或两个以上的线程时,假如每个线程都占据一个资源并恳求另一个资源,这时就会呈现死锁情形.因为假如一个线程不能获得资源,则全部线程都不能持续履行,我们称那个特定的线程被阻塞;假如每个线程都由于同组中另一个线程所占据的资源而被阻塞,我们就称这个线程组被死锁.
在本文中,我们将谈论发生在典型的重要J2EE利用程序中的两大类死锁情形:“简单”数据库死锁和跨资源死锁.固然我们的谈论基于J2EE平台,但也实用于其他技术平台.
数据库死锁
在数据库中,假如一个衔接占用了另一个衔接所需的数据库锁,则它可以阻塞另一个衔接.假如两个或两个以上的衔接彼此阻塞,则它们都不能持续履行,这种情形称为死锁.
数据库死锁问题不易处理,这是因为触及到的锁定普通不是显式的.普通,对数据行举行隐式更新时,需求锁定该数据行,履行更新,然后在提交或回滚封闭事件时释放锁.由于数据库平台、配置的断绝级以及查询提醒的差别,获得的锁大概是细粒度或粗粒度的,它会阻塞(或不阻塞)其他对同一数据行、表或数据库的查询.
获得的锁依靠于内部生成的查询筹划.当数据大小和分步随时间发生改变时,该筹划也大概改变.这样在一个环境中获得一组锁的查询可以尝试在另一个环境中获得一组完好差别的锁.必要时,数据库可以随便地增添它的锁.比方,数据库大概会挑选锁定整页,而不是锁定同一数据页中的10个数据行,这会阻塞对无需锁定的数据行的读写权限.
基于数据库情势,读写操作会要求遍历或更新多个索引、考证约束、履行触发器等.每个要求城市引入更多锁.此外,其他利用程序还大概正在拜候同一数据库情势中的某些对象,并获得差别于您的利用程序所具有的锁.
全部这些因素综合在一同,数据库死锁几近不大概被消除了.值得庆幸的是,数据库死锁普通是可恢复的:当数据库发现死锁时,它会强迫销毁一个衔接(普通是利用最少的衔接),并回滚其事件.这将释放全部与已经完毕的事件相关联的锁,至少答应其他衔接中有一个可以获得它们正在被阻塞的锁.
由于数据库具有这种典型的死锁处理行为,所以当呈现数据库死锁问题时,数据库常常只能重试整个事件.当数据库衔接被销毁时,会抛出可被利用程序捕捉的非常,并标识为数据库死锁情形.假如答应死锁非常转到达初始化该事件的代码层之外,则该代码层可以只启动一个新事件并重做先前全部工作.要精确利用此战略,则在事件成功提交之前,它的代码不能有其他操作.注意:要限制重试次数,不然易招致死锁的代码块会永久循环下去.
假如呈现问题就重试,这种办法有点笨.但是,由于数据库可以安闲地获得锁,所以几近不大概保证两个或两个以上的线程不发生数据库死锁.此办法至少能保证在呈现某些罕有的数据库死锁情形时,利用程序能正常运行.这比要求用户去重试操作要好得多.
在J2EE利用程序中,开辟人员可以设置一个EJB调用以利用Bean托管事件(BMT)——开辟人员启动、提交或回滚特定的事件或容器托管事件(CMT)——调用办法前启动事件,并在办法完成后提交或回滚事件.假如EJB供应商供应retry-on-deadlock参数,从而可以通过容器托管事件自动完成此操作,那当然再好不过了.假如没有这种自动功效,开辟人员终究将仅为了对死锁举行重试而强迫EJB调用利用Bean托管事件.
碰到死锁问题和锁定其他线程的锁的具体频率在很大程度上取决于数据库平台、硬件、数据库情势和查询.在利用基于锁的并发掌握的数据库(如MSSQL)中,未提交的写操作会禁止读操作,而未提交的读操作会禁止写操作,使数据库更易呈现死锁问题.在多版本并发掌握(MVCC)数据库(如Oracle)中,未提交的写操作不禁止读操作——读操作仅查看旧版本数据行.这固然会引入其他问题,但不会造成一样多的死锁机会.我们要让自己熟习这些数据库锁定情势,并注意自己正在利用的范例.
在查找、修复以及避免数据库死锁方面,有一些很好的参考办法,但它们都不能完好消除死锁的大概性.
以上是“<b>对J2EE中死锁问题的研究</b>[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |