面试官:请写一段能造成死锁的代码。(附:定位死锁的方法)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://junmoxiao.blog.csdn.net/article/details/99304473

思路:定义2个锁、2个方法,2个方法获取锁的顺序相反,且中间有休眠时间。
这样启动2个线程分别运行这2个方法,2个线程会一直处于等锁状态。

public class NormalDeadLock {
    private static Object valueFirst = new Object();//第一个锁
    private static Object valueSecond = new Object();//第二个锁

    //先拿第一个锁,再拿第二个锁
    private static void fisrtToSecond() throws InterruptedException {
        String threadName = Thread.currentThread().getName();
        synchronized (valueFirst){
            System.out.println(threadName+" get 1st");
            Thread.sleep(100);
            synchronized (valueSecond){
                System.out.println(threadName+" get 2nd");
            }
        }
    }

    //先拿第二个锁,再拿第一个锁
    private static void SecondToFisrt() throws InterruptedException {
        String threadName = Thread.currentThread().getName();
        synchronized (valueSecond){
            System.out.println(threadName+" get 2nd");
            Thread.sleep(100);
            synchronized (valueFirst){
                System.out.println(threadName+" get 1st");
            }
        }
    }

    private static class TestThread extends Thread{

        private String name;

        public TestThread(String name) {
            this.name = name;
        }

        public void run(){
            Thread.currentThread().setName(name);
            try {
                SecondToFisrt();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Thread.currentThread().setName("TestDeadLock");
        //新建一个线程,先拿第2个锁,再拿第1个锁。
        TestThread testThread = new TestThread("SubTestThread");
        testThread.start();
        try {
        //主线程,先拿第1个锁,再拿第2个锁。
            fisrtToSecond();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果:
在这里插入图片描述
如何定位死锁:
方法一:

  1. 找到jdk下bin的位置cmd,执行命令
    jps -v
    在这里插入图片描述
  2. 定位死锁:
    jstack 16260
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

方法二:
在这里插入图片描述
点击这个,能出现和方法一一样的内容。

这样的死锁叫简单顺序死锁,其实我们可以眼看出来哪里有问题。

解决方案:
将2个方法获取锁的顺序修改成一样就可以了。

参考:Mark—笔记_Java并发编程

自定义函数造成死锁,能帮着看看吗

05-20

这个一个老大帮着写的自定义函数,一直用的好好的。但是最近发现sql总是死锁,后来发现原来出在这个函数上面。能帮着改改吗,是因为执行时间太长所以死锁的吗? rn rn/*--news统计相关文章数--*/ rnCREATE function f_news_linknum(@ArticleID int,@num int) rnreturns int rnas rnbegin rn declare @t1 table(nkey varchar(200)) rn declare @t2 table(ArticleID int,nkey varchar(200)) rn declare @nkey varchar(200),@cnt int rn rn select @nkey=nkey from article where articleid=@ArticleID rn rn if isnull(@nkey,'')='' rn return 0 rn rn while (charindex(',',@nkey)>0) rn begin rn insert into @t1 select left(@nkey,charindex(',',@nkey)-1) rn set @nkey = stuff(@nkey,1,charindex(',',@nkey),'') rn end rn insert into @t1 select @nkey rn rn if (select count(*) from @t1)<@num rn return 0 rn rn rn insert into @t2 rn select rn a.ArticleID,b.nkey rn from rn article a,@t1 b rn where rn a.articleid!=@ArticleID rn and rn charindex(','+b.nkey+',',','+a.nkey+',')>0 rn rn select @cnt=count(*) rn from (select ArticleID from @t2 group by ArticleID having count(*)>=@num) t rn rn return @cnt rnend rn rn rn使用方法: rn rn/*--更新文章的相关文章数--*/ rnupdate article rnset rn link1 =dbo.f_news_linknum(ArticleID, 1), rn link2 =dbo.f_news_linknum(ArticleID, 2), rn link3 =dbo.f_news_linknum(ArticleID, 3), rn link4 =dbo.f_news_linknum(ArticleID, 4), rn link5 =dbo.f_news_linknum(ArticleID, 5), rn link6 =dbo.f_news_linknum(ArticleID, 6), rn link7 =dbo.f_news_linknum(ArticleID, 7), rn link8 =dbo.f_news_linknum(ArticleID, 8), rn link9 =dbo.f_news_linknum(ArticleID, 9), rn link10=dbo.f_news_linknum(ArticleID,10) rn rn我即使把这个语句拆成10个,也还是时间超长,造成死锁。怎么改一下呢。问题的关键在哪里? 论坛

sqlserver之定位死锁(经验分享)

07-14

很多人都遇到过这样的情况,当网站达到一定的访问量,数据库就会成为瓶颈,有可能发生死锁,进而引起阻塞。rnrn有人认为这可能就是硬件的极限了,于是想办法增加硬件设备。而我本人认为问题的元凶可能是性能不高的sql脚本,引起了死锁,进而导致阻塞。rnrn如果你和我有相同的看法,那我们就一起想办法找出问题的源头。rnrn案例1.rnrn某一天我被告知,我们的书城网站不能访问了,我马上查看,发现书城的有两台iis服务器均显示service unavailable,如果我断定是sqlserver数据库发生了死锁。rnrn要知道是否发生了死锁,当然要看master库的sysprocess表,看看是否有什么进程堵住了别的进程,语句如下:rnrnSelect * from master..sysprocesses where blocked > 0rnrn很快我发现,有一个blocked = 51 堵住了很多进程(查看blocked列可见),果然和我的判断吻合;为了进一步找出发生死锁的语句,我用到的如下的语句rnrndbcc inputbuffer(51);rnrn结果如下:rnrnEventType Parameters EventInfo rnrn------------------------------------------------rnrnRPC Event 0 p_Book_content;1rnrn从上面就可以看出是p_Book_content 这个过程引起的阻塞,但是这个过程里面同时对多个表进行了操作,到底是那个语句出了问题呢?rnrn下面我们再来进一步定位死锁的位置:rnrnSp_lock rnrn结果如下(大部分数据略)rnrnSpid dbid objid indid type resource mode statusrnrn-------------------------------------------------------------------------------------------------rnrn51 14 206623779 0 TAB X WAITrnrn52 14 0 0 DB S GRANTrnrn53 14 0 0 DB S GRANTrnrn。。。rnrn。。。rnrn。。。rnrn现在我们来看看spid = 51 这行, mode = X 表示排它锁, status = WAIT表示正在等待(即阻塞了),dbid = 14 是数据库的id,objid = 206623779 是被锁的对象id,我们可以通过下列函数得到数据库和表:rnrnSelect db_name(@dbid) -----》book_dbrnrnselect object_name(@objid) -------》 t_bookrnrn即book_db库的t_book表被锁住了,这时候再回投仔细检查 p_Book_content 存储过程,发现只有一个语句对t_book进行了操作: rnrnupdate t_book set hitcount = hitcount + 1 where bookid = @bookid rnrn这个语句的作用是更新书本的点击次数,为什么上面这个语句会引起死锁呢?我认为最可能的情况应该是同时访问的人过多,同时对表进行过多的update操作引起的,所以最终改用别的方式,不再实时对t_book表进行update操作,而是每次访问都先insert一条记录到一个中间表中,然后再用一个作业,每隔10分钟定时更新书本的点击次数,如此改进之后,此问题终于圆满解决了。rnrn相关资料在book online可以找到, 关键字: sp_lock , sysprocesses , dbcc inputbuffer , db_name(), object_name()rnrn------------------------------------------------rn读别人的经验是不错的学习方式,希望可以看到高手们的经验rnrn 论坛

请大家帮我分析这段代码造成死锁的原因

01-29

尊敬的各位论坛的小伙伴们,对于下列代码不能解释清楚死锁的原因:rn首先贴代码吧:rnAccount.javarnpublic class Account rn private String acccountNo;rn private double balance;rn private volatile boolean flag = false;rn private int i = 0;rnrn public Account() rnrn rnrn public Account(String accountNo, double balance) rn this.acccountNo = acccountNo;rn this.balance = balance;rn rnrn public String getAcccountNo() rn return acccountNo;rn rnrn public void setAcccountNo(String acccountNo) rn this.acccountNo = acccountNo;rn rnrn public double getBalance() rn return this.balance;rn rnrn public void draw(double drawAmount) rn synchronized (Account.class) rn if (!flag) rn try rn Account.class.wait();rn catch (InterruptedException e) rn // TODO Auto-generated catch blockrn e.printStackTrace();rn rn else rn System.out.println(Thread.currentThread().getName() + "取钱:" + drawAmount);rn balance -= drawAmount;rn System.out.println("账户余额为:" + balance);rn // 将标识账户是否有存款的旗标设为falsern if (balance < 0) rn i++;rn System.out.println(rn "******************************************************************************************************************************************"rn + i);rn flag = false;rn Account.class.notifyAll();rn rn rn System.out.println(flag);rn rnrn rnrn public void deposit(double depositAmount) rn synchronized (Account.class) rn if (flag) rn try rn Account.class.wait();rn catch (InterruptedException e) rn // TODO Auto-generated catch blockrn e.printStackTrace();rn rn else rn System.out.println(Thread.currentThread().getName() + "存款:" + depositAmount);rn balance += depositAmount;rn System.out.println("账户余额为:" + balance);rn if (balance > 0) rn flag = true;rn Account.class.notifyAll();rn rn rn System.out.println(flag);rn rn rnrnDepositThread.javarnpublic class DepositThread extends Thread rn // 模拟用户账户rn private Account account;rn private double depositAmount;rnrn public DepositThread(String name, Account account, double depositAmount) rn super(name);rn this.account = account;rn this.depositAmount = depositAmount;rn rnrn @Overridern public void run() rn for (int i = 0; i < 100; i++) rn account.deposit(depositAmount);rn rn rnrnrnDrawThread.javarnpublic class DrawThread extends Thread rn private Account account;rn private double drawAmount;rnrn public DrawThread(String name, Account account, double drawAmount) rn super(name);rn this.account = account;rn this.drawAmount = drawAmount;rn rnrn @Overridern public void run() rn for(int i=0;i<100;i++) rn account.draw(drawAmount);rn rn rnrn测试代码:rnDrawTest.javarnpublic class DrawTest rn public static void main(String[] args) rn // 创建一个账户rn Account acct = new Account("1234567", 0);rn new DrawThread("取钱者甲", acct, 80000).start();rn new DrawThread("取钱者乙", acct, 80000).start();rn new DrawThread("取钱者丙", acct, 80000).start();rnrn new DepositThread("存钱者张", acct, 80000).start();rn new DepositThread("存钱者王", acct, 80000).start();rn new DepositThread("存钱者刘", acct, 80000).start();rn rnrnrn请大家帮我分析这段代码造成死锁的原因 论坛

没有更多推荐了,返回首页