zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    如何解决App无法收到android开机广播
    如何实现开机启动、清缓存、杀进程、悬浮窗口单双击区分,附源码
    WaitForSingleObject 介绍【转】
    C++ Unicode SBCS 函数对照表【转】
    数字IP字符串IP转换
    打印内存【CSDN】
    巧妙的无重复随机数方法
    <unnamedtag>”后面接“int”是非法的
    友元函数与重载运算符【转】
    QT QTableWidget 用法总结【转】
  • 原文地址:https://www.cnblogs.com/Latiny/p/10659609.html
Copyright © 2011-2022 走看看