什么是死锁?
抽象解释就是两个或多个不同的线程相互持有并等待对方所占有的临界区资源而不释放所造成的线程永久阻塞的现象。
举个例子通俗解释一下:
有两个线程thread1和thread2,2个临界区资源A和B,thread1想访问资源A然后访问资源B,thread2想访问资源B然后访问资源A。在多线程中,对临界区资源的访问必须是互斥的,也就是在访问临界区资源之前要先获得一把锁,访问完之后释放这把锁,让其他线程拿到这把锁再访问这个资源。假设对资源A的访问需要使用锁a,对资源B的访问需要使用锁b。
thread1先拿到锁a,然后访问资源A,在访问资源A的过程中它又要访问资源B,所以它要尝试获取锁b,与此同时,thread2拿到了锁b,并正在访问资源B,所以thread1会被阻塞掉;thread2在访问资源B的过程中,它又要访问资源A,所以它尝试获取锁a,但是很不幸,锁a正被thread1用了还没有释放,它需要拿到锁b并访问资源B之后才会释放锁a,所以thread2也会被阻塞掉。因此thread1和thread2都在等待对方所占用的资源,谁也不会先释放,这种循环等待会永久得持续下去,导致两个线程都永久地阻塞下去。
如何避免死锁?
从以上对死锁的解释可以看出,当线程满足条件(1)需要互斥访问同样的临界区资源,(2)一个线程按照另一个线程相反的顺序访问某些临界区资源,的时候会发生死锁。即存在锁套锁。
因此可以让线程都按照同样的顺序去访问临界区资源,这样就可以避免死锁的发生。对于上面的例子,就是thread1先访问资源A再访问资源B,让thread2也先访问资源A再访问资源B。