MySQL中死锁相关的问题

死锁

  1. 概念:当A事务拥有锁1需要锁2,同时B事务拥有锁2需要锁1的时候,两个线程就进入了天荒地老的循环等待,这就是死锁。

  2. 预防死锁:两种办法

    1. 设定锁等待时间:如果超过一定时间没有获取到锁就暂时放弃,然后回滚,此时会自动释放当前事务持有的锁
    2. 被锁时发起死锁检测:当一个线程被锁的时候就要找到他正在等待释放锁的线程,再递归着去找这个线程等待的线程,如果发现环就证明死锁了,那该回退就回退、该释放就释放。死锁检测还是挺耗时的,如果是简单的两个事务成环那两下就判断出来了,但一般没死锁要递归判断很多次,几乎是个O(n)的操作,这导致死锁检测占用很多CPU资源,虽然没死锁了但是事务又处理不了几个。
  3. 场景题:怎么解决热点行更新导致的性能问题?三个办法

    1. 关掉死锁检测:如果你能确保这个业务一定不会出现死锁,可以临时关闭死锁检测
    2. 控制并发度:控制更新同一行的线程的数量,降低死锁检测的成本
    3. 一个数据行改成逻辑上的多个数据行来减少锁冲突。比如银行账户余额这一行记录,可以分成10行记录的和,冲突概率就减小为 1/10,降低发生冲突的线程数,降低死锁检测的成本。
  4. 写一个死锁的例子

public class DeadLock implements Runnable{
    private static final Object lock1=new Object();
    private static final Object lock2=new Object();
    private int flag;

    public DeadLock(int flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if(flag==1)
        {
            synchronized (lock1)
            {
                System.out.println(Thread.currentThread().getName()+"获取lock1并希望获得lock2");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2)
                {
                    System.out.println(Thread.currentThread().getName()+"获取lock2");
                }
            }
        }
        else
        {
            synchronized (lock2)
            {
                System.out.println(Thread.currentThread().getName()+"获取lock2并希望获得lock1");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1)
                {
                    System.out.println(Thread.currentThread().getName()+"获取lock1");
                }
            }
        }
    }

    public static void main(String [] args){
        DeadLock d1=new DeadLock(0);
        DeadLock d2=new DeadLock(1);
        Thread t1=new Thread(d1);
        Thread t2=new Thread(d2);
//        t1.run();
//        t2.run();
//        不可以用run(),因为run()会等待线程执行完才能执行下一个线程,不是并发的
        t1.start();
        t2.start();
    }
//输出结果
//Thread-0获取lock2并希望获得lock1
//Thread-1获取lock1并希望获得lock2
}
#Java开发##春招##实习##笔试题目##MySQL##学习路径##后端开发#
全部评论
感谢楼主对死锁的讲解!
点赞
送花
回复
分享
发布于 2022-03-13 01:09
欢迎关注公众号「编程学习指南」回复「面试」获取实习生招聘笔试面试面经全套资料(含优秀简历模板、笔试题、面试题、面经)!并且提供免费简历修改服务!以及内推!
点赞
送花
回复
分享
发布于 2022-03-20 18:31
秋招专场
校招火热招聘中
官网直投
写的挺好的
点赞
送花
回复
分享
发布于 2022-03-20 18:31

相关推荐

7 76 评论
分享
牛客网
牛客企业服务