1、多线程死锁


a. 死锁分析:


   假设A和B同时在吃意大利面,而吃意大利面的条件是左手使用汤勺,右手使用叉子。现在只有一副餐具,A拿到了汤勺,B拿到了叉子,A等待B放下叉子,B等待A放下汤勺。则形成了死锁。


b. 出现死锁的条件:

  • 具有多个SharedResource参与者,相当于汤勺和叉子。
  • 线程锁定了一个SharedResource之后,在未解锁的情况下去锁定另一个SharedResource参与者,相当于A在拥有了汤勺之后,又去拿叉子;B在拥有了叉子之后又去拿汤勺。
  • 获取SharedResource参与者的顺序不固定,参与者顺序对等,相当于汤勺和叉子的顺序相同,没有先后关系。


c. 上述1、2、3三个条件只要破坏了其中一种,则就解决了死锁的问题。


2、提高多线程执行性能的两种方式:


减少 SharedResource参与者参与者的个数,从而减少synchronized使用数量,减少获取对象锁的操作时间

尽量缩短临界区范围,从而减少线程冲突时等待的时间。


3、自己设计线程锁

oid method() {
    lock(); //
    try {
        ..
    } finally {
        unlock(); //最后无论什么情况都要解锁
    }
}

4、原子操作

  • 用synchronized定义的方法或者块都具有原子性,只能被一个线程使用
  • long、double为非原子性,其他类型以及对象等引用都是具有原子性
  • 在定义long、double类型变量时,使用volatile修饰,表示对这个字段变量的定义为不可分隔的

总结:

  • 基本类型、引用类型为原子操作
  • long、double为可以分割的
  • 在多线程中使用其作为共享参与者使用时,要么在使用时的方法用synchronized定义,或者使用volatile声明
5、意大利面死锁问题解决方案

设计思路是将汤勺和叉子作为一个整体去处理,这样就解决了死锁的问题。
还有一种方法就是在添加汤勺和叉子时是有序的,必须先拿汤勺,再拿叉子,这样也可以解决死锁问题。


//主方法,用于创建处理
public class Main {
    public static void main(String[] args) {
        Tool spoon = new Tool("spoon");
        Tool fork = new Tool("fork");
        Tools tools = new Tools(spoon, fork);
        new EaterThread(tools, "shma").start();
        new EaterThread(tools, "jjq").start();
    }

}
 1 // 吃意大利面的线程 不断的吃
 2 class EaterThread extends Thread {
 3     private String name;
 4     private final Tool leftHand;
 5     private final Tool rightHand;
 6     public EaterThread(Tools tools, String name) {
 7         super();
 8         this.leftHand = tools.getSpoon();
 9         this.name = name;
10         this.rightHand = tools.getFork();
11     }
12     public void eat() {
13         synchronized(leftHand) {
14             System.out.println(name + " takes up " + leftHand + "(left)");
15             synchronized(rightHand) {
16                 System.out.println(name + " takes up " + rightHand + "(right)");
17                 System.out.println(name + " is eating now!");
18                 System.out.println(name + " puts down " + rightHand + "(right)");
19             }
20             System.out.println(name + " puts down " + leftHand + "(left)");
21         }
22     }
23 
24     @Override
25     public void run() {
26         while(true) {
27             eat();
28             try {
29                 Thread.sleep(1000);
30             } catch (InterruptedException e) {
31                 // TODO Auto-generated catch block
32                 e.printStackTrace();
33             }
34         }
35     }
36 
37 }


只有注册用户登录后才能发表评论。


网站导航:
 

posts - 0, comments - 0, trackbacks - 0, articles - 2

Copyright © 马少

版权所有 侵权必究