Java死锁

与世无争的帅哥 提交于 2020-01-11 23:25:55

所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象

一.出现死锁的原因

  (1)交叉锁可导致程序出现死锁

    线程A持有R1的锁等待获取R2的锁,线程B持有R2的锁等待R1的锁,这种情况最容易导致程序发生死锁的问题

  (2)内存不足

    当并发请求系统可用内存时,如果此时系统内存不足,则可能会出现锁的情况。两个线程T1和T2,执行某个任务,其中T1已经获取了10MB内存,T2获取了20MB内存,如果每个线程的执行单元都需要30MB的内存,但是剩余可用的         内存刚好是20MB,那么两个线程有可能都在等待彼此能够释放内存资源

  (3)一问一答式的数据交换

    服务端开启某个端口,等待客户端访问,客户端发送请求立即等待接收,由于某种原因服务端错过了客户端的请求,仍然在等待一问一答的数据交互,此时服务端和客户端都在等待对方发送数据。

  (4)数据库锁

    无论是数据库表级别的锁,还是行级别的锁,比如某个线程执行for  update语句退出了事物,其它此案成访问该数据库都将陷入死锁

  (5)文件锁

    某线程获得文件锁意外退出,其它读取该文件的线程也将进入死锁直到系统释放文件句柄资源

  (6)死循环引起的死锁

    程序由于代码原因或者某些异常处理不当,进入死循环,虽然查看堆栈信息不会出现任何死锁的迹象,但是程序不工作,CPU占有率居高不下,这种死锁被称为系统假死

二、交叉死锁举例

package 死锁;

public class DeadLock {
    
    private final Object READ = new Object();
    private final Object WRITE = new Object();
    
    public void read()
    {
        synchronized(READ)
        {
            System.out.println(Thread.currentThread().getName()+"  get READ lock");
            synchronized(WRITE)
            {
                System.out.println(Thread.currentThread().getName()+"  get WRITE lock");
            }
            System.out.println(Thread.currentThread().getName()+"  release WRITE lock");
        }
        System.out.println(Thread.currentThread().getName()+"  release READ lock");
    }
    
    
    public void write()
    {
        synchronized(WRITE)
        {
            System.out.println(Thread.currentThread().getName()+"  get WRITE lock");
            synchronized(READ)
            {
                System.out.println(Thread.currentThread().getName()+"  get READ lock");
            }
            System.out.println(Thread.currentThread().getName()+"  release READ lock");
        }
        System.out.println(Thread.currentThread().getName()+"  release WRITE lock");
    }
    
    public static void main(String[] args) {
        final DeadLock deadLock = new DeadLock();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                while(true)
                {
                    deadLock.read();
                }
            }
        },"READ-THREAD").start();
        
    new Thread(new Runnable() {
                
                @Override
                public void run() {
                    while(true)
                    {
                        deadLock.write();
                    }
                }
            },"WRITE-THREAD").start();
        }
}

 三、交叉锁引起的死锁诊断

    运行DeadLock,程序将陷入死锁,打开jstack或者jconsole工具,Jstack-l PID会直接发现死锁的信息

    

    一般交叉死锁引起的锁线程都会是BLOCKED状态,CPU占用资源不高,很容易借助工具来发现

说明:摘自《JAVA高并发编程详解-多线程与架构设计》

链接:https://pan.baidu.com/s/1BHH2X0lCt2xGz-U7ryTbIA
提取码:qx40 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!