线程同步死锁

Posted bfcs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程同步死锁相关的知识,希望对你有一定的参考价值。

1.线程同步(即上锁,同步锁)实现的方式

1)同步代码块

synchronized(obj){  //obj称为同步监视器,obj要监视的对象

}

同步监视器只能是对象,推荐使用共享资源的对象,可以当前对象 this,也可以是其它的对象

技术图片
 1 public class Ticket1 implements Runnable{
 2     private int ticket=5;
 3     @Override
 4     public void run() {
 5         for(int i=0;i<100;i++){  //每个窗口排了100个人
 6             synchronized (this) {  //同步代码块
 7                 if(ticket>0){//有票
 8                     try {
 9                         Thread.sleep(300);
10                     } catch (InterruptedException e) {
11                         // TODO Auto-generated catch block
12                         e.printStackTrace();
13                     }
14                     System.out.println(Thread.currentThread().getName()+"正在卖第"+(ticket--)+"张票");
15                 }
16             }
17         }
18     }
19 }
View Code
技术图片
 1 public class TestTicket1 {
 2     public static void main(String[] args) {
 3         Ticket1 ticket=new Ticket1();
 4         //创建Thread类
 5         Thread t1=new Thread(ticket, "A窗口");
 6         Thread t2=new Thread(ticket,"B窗口");
 7         Thread t3=new Thread(ticket,"C窗口");
 8         //启动线程
 9         t1.start();
10         t2.start();
11         t3.start();
12     }
13 }
View Code

 

2)同步方法

同步方法的同步监视器为当前对象this

public synchronized void 方法名(参数列表){

}

技术图片
 1 public class Ticket2 implements Runnable{
 2     private int ticket=5;
 3     @Override
 4     public void run() {
 5         for(int i=0;i<100;i++){  //每个窗口排了100个人
 6              //调用同步方法
 7             this.saleTicket();
 8         }
 9     }
10     private synchronized void saleTicket(){  //无需指定同步监视器,同步监视器只能是当前对象this
11         if(ticket>0){//有票
12             try {
13                 Thread.sleep(300);
14             } catch (InterruptedException e) {
15                 // TODO Auto-generated catch block
16                 e.printStackTrace();
17             }
18             System.out.println(Thread.currentThread().getName()+"正在卖第"+(ticket--)+"张票");
19         }
20     }
21 }
View Code
技术图片
 1 public class TestTicket2 {
 2     public static void main(String[] args) {
 3         Ticket2 ticket=new Ticket2();
 4         //创建Thread类
 5         Thread t1=new Thread(ticket, "A窗口");
 6         Thread t2=new Thread(ticket,"B窗口");
 7         Thread t3=new Thread(ticket,"C窗口");
 8         //启动线程
 9         t1.start();
10         t2.start();
11         t3.start();
12     }
13 }
View Code

 

2.死锁及解决

产生原因:多线程操作时,互相等待对方的资源

技术图片

技术图片
 1 public class DeadLock extends Thread {
 2     private Object money;//
 3     private Object water;//
 4     public boolean flag;//标识持有对象锁
 5     
 6     public DeadLock(Object money, Object water) {
 7         super();
 8         this.money = money;
 9         this.water = water;
10     }
11 
12     @Override
13     public void run() {
14         if(flag){//true时,持有“钱”的锁
15             synchronized (money) {
16                 System.out.println("有钱,等水");
17                 try {
18                     Thread.sleep(300);
19                 } catch (InterruptedException e) {
20                     // TODO Auto-generated catch block
21                     e.printStackTrace();
22                 }
23                 synchronized (water) {
24                     System.out.println("有水,等钱");
25                 }
26             }
27         }else{
28             synchronized (water) {
29                 System.out.println("有水,等钱");
30                 try {
31                     Thread.sleep(300);
32                 } catch (InterruptedException e) {
33                     // TODO Auto-generated catch block
34                     e.printStackTrace();
35                 }
36                 synchronized (money) {
37                     System.out.println("有钱,等水");
38                 }
39             }
40             
41         }
42     }
43 }
View Code
技术图片
 1 public class Test {
 2     public static void main(String[] args) {
 3         //创建共享资源的对象
 4         Object money=new Object();
 5         Object water=new Object();
 6         //创建线程类的对象
 7         DeadLock d1=new DeadLock(money, water);
 8         DeadLock d2=new DeadLock(money, water);
 9         d1.flag=true;
10         d2.flag=false;
11         //启动线程
12         d1.start();
13         d2.start();
14     }
15 }
View Code

技术图片

无法完成一个循环

 

如何解决死锁:不要让两个对象同时持有对象锁,采用互斥方式来解决

 把 synchronized嵌套改为同级并列

技术图片
 1 public class DeadLock2 extends Thread {
 2     private Object money;//
 3     private Object water;//
 4     public boolean flag;//标识持有对象锁
 5     
 6     public DeadLock2(Object money, Object water) {
 7         super();
 8         this.money = money;
 9         this.water = water;
10     }
11 
12     @Override
13     public void run() {
14         if(flag){//true时,持有“钱”的锁
15             synchronized (money) {
16                 System.out.println("有钱,等水");
17                 try {
18                     Thread.sleep(300);
19                 } catch (InterruptedException e) {
20                     // TODO Auto-generated catch block
21                     e.printStackTrace();
22                 }
23                 
24             }
25             synchronized (water) {
26                 System.out.println("有水,等钱");
27             }
28         }else{
29             synchronized (water) {
30                 System.out.println("有水,等钱");
31                 try {
32                     Thread.sleep(300);
33                 } catch (InterruptedException e) {
34                     // TODO Auto-generated catch block
35                     e.printStackTrace();
36                 }
37                 
38             }
39             synchronized (money) {
40                 System.out.println("有钱,等水");
41             }
42             
43         }
44     }
View Code
技术图片
 1 public class Test2 {
 2     public static void main(String[] args) {
 3         //创建共享资源的对象
 4         Object money=new Object();
 5         Object water=new Object();
 6         //创建线程类的对象
 7         DeadLock2 d1=new DeadLock2(money, water);
 8         DeadLock2 d2=new DeadLock2(money, water);
 9         d1.flag=true;
10         d2.flag=false;
11         //启动线程
12         d1.start();
13         d2.start();
14     }
15 }
View Code

技术图片

死锁的避免

银行家算法:该算法需要检查申请者对资源的最大需求量,如果系统现存的各类资源可以满足申请者的请求,就满足申请者的请求。这样申请者就可很快完成其计算,然后释放它

占用的资源,从而保证了系统中的所有进程都能完成,所以可避免死锁的发生。(计算资源的大小,计算出来后,永远按照从大到小的方式来获得锁)

以上是关于线程同步死锁的主要内容,如果未能解决你的问题,请参考以下文章

Java_线程同步和死锁

线程同步

线程同步死锁

Java之线程,常用方法,线程同步,死锁

Java中线程死锁问题

Android多线程研究——线程同步和相互排斥及死锁