4 线程死锁

1 死锁定义

所谓死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。死锁是多线程程序设计带来的负面效果,在程序设计时需要防止死锁的发生。

2 死锁的必要条件

(1) 互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

(2) 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。

(3) 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

(4) 循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求。即存在一个处于等待状态的进程集合{Pl, P2, ..., pn},其中Pi等 待的资源被P(i+1)占有(i=0, 1, ..., n-1),Pn等待的资源被P0占有,如图1所示。

3 死锁实例

(1)同步代码块死锁

public class DeadLockTest {

    public static void main(String[] args) {
        Customer customer = new Customer();
        Hotel hotel = new Hotel();

        new Thread(new Dining(customer, hotel)).start();
        new Thread(new Pay(customer, hotel)).start();
    }
}

class Dining implements Runnable {

    private Customer customer;
    private Hotel hotel;

    public Dining(Customer customer, Hotel hotel) {
        this.customer = customer;
        this.hotel = hotel;
    }

    @Override
    public void run() {
        synchronized (customer) {
            customer.dining();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (hotel) {
                hotel.service();
            }
        }
    }
}

class Pay implements Runnable {

    private Customer customer;
    private Hotel hotel;

    public Pay(Customer customer, Hotel hotel) {
        this.customer = customer;
        this.hotel = hotel;
    }

    @Override
    public void run() {
        synchronized (hotel) {
            hotel.bill();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (customer) {
                customer.pay();
            }
        }
    }
}
View Code
class Customer {

    public void pay() {
        System.out.println("顾客买单");
    }

    public void dining() {
        System.out.println("顾客用餐");
    }
}

class Hotel {

    public void service() {
        System.out.println("上菜");
    }

    public void bill() {
        System.out.println("请先买单");
    }
}
View Code

(2) 同步方法死锁

public class DeadLockDemo {

    public static void main(String[] args) {
        new DeadThread();
    }
}

class Customers {

    public synchronized void dining(Waiter w) {
        System.out.println("先吃饭再买单");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        w.doService();
    }

    public synchronized void pay() {
        System.out.println("同意,先买单吧");
    }
}

class Waiter {
    public synchronized void bill(Customers c) {
        System.out.println("先买单再吃饭");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        c.pay();
    }

    public synchronized void doService() {
        System.out.println("同意,先吃饭吧");
    }
}

class DeadThread implements Runnable {
    Customers customer = new Customers();
    Waiter waiter = new Waiter();

    public DeadThread() {
        new Thread(this).start();
        waiter.bill(customer);
    }

    @Override
    public void run() {
        customer.dining(waiter);
    }
}
View Code
原文地址:https://www.cnblogs.com/Latiny/p/10659609.html