Android(java)学习笔记10:同步中的死锁问题以及线程通信问题

1. 同步弊端:

(1)效率低

(2)如果出现了同步嵌套,就容易产生死锁问题

死锁问题及其代码 :

(1)是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象

(2)同步代码块的嵌套案例

1 package cn.itcast_02;
2 
3 public class MyLock {
4     // 创建两把锁对象
5     public static final Object objA = new Object();
6     public static final Object objB = new Object();
7 }
 1 package cn.itcast_02;
 2 
 3 public class DieLock extends Thread {
 4 
 5     private boolean flag;
 6 
 7     public DieLock(boolean flag) {
 8         this.flag = flag;
 9     }
10 
11     @Override
12     public void run() {
13         if (flag) {
14             synchronized (MyLock.objA) {
15                 System.out.println("if objA");
16                 synchronized (MyLock.objB) {
17                     System.out.println("if objB");
18                 }
19             }
20         } else {
21             synchronized (MyLock.objB) {
22                 System.out.println("else objB");
23                 synchronized (MyLock.objA) {
24                     System.out.println("else objA");
25                 }
26             }
27         }
28     }
29 }
 1 package cn.itcast_02;
 2 
 3 /*
 4  * 同步的弊端:
 5  *         A:效率低
 6  *         B:容易产生死锁
 7  * 
 8  * 死锁:
 9  *         两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象。
10  * 
11  * 举例:
12  *         中国人,美国人吃饭案例。
13  *         正常情况:
14  *             中国人:筷子两支
15  *             美国人:刀和叉
16  *         现在:
17  *             中国人:筷子1支,刀一把
18  *             美国人:筷子1支,叉一把
19  */
20 public class DieLockDemo {
21     public static void main(String[] args) {
22         DieLock dl1 = new DieLock(true);
23         DieLock dl2 = new DieLock(false);
24 
25         dl1.start();
26         dl2.start();
27     }
28 }

我们执行的时候会发现程序会锁住(当然这个只是很大几率会锁住):如下图

这里死锁我们该怎么解决呢?这里引出了线程之间通信:

不同种类的线程针对同一个资源的操作

2. 下面设置线程(生产者)和获取线程(消费者针对同一个学生对象进行操作示例:

代码实现:

 1 package cn.itcast_03;
 2 
 3 /*
 4  * 分析:
 5  *         资源类:Student    
 6  *         设置学生数据:SetThread(生产者)
 7  *         获取学生数据:GetThread(消费者)
 8  *         测试类:StudentDemo
 9  * 
10  * 问题1:按照思路写代码,发现数据每次都是:null---0
11  * 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个
12  * 如何实现呢?这里是共享资源一种思路
13  *         在外界把这个数据创建出来,通过构造方法传递给其他的类。
14  * 
15  */
16 public class StudentDemo {
17     public static void main(String[] args) {
18         //创建资源----外界创建出资源
19         Student s = new Student();
20         
21         //设置和获取的类(这两个线程类被刚刚创建的资源绑定)
22         SetThread st = new SetThread(s);//通过构造方法传递给其他类
23         GetThread gt = new GetThread(s);//通过构造方法传递给其他类
24 
25         //线程类
26         Thread t1 = new Thread(st);
27         Thread t2 = new Thread(gt);
28 
29         //启动线程
30         t1.start();
31         t2.start();
32     }
33 }
 1 package cn.itcast_03;
 2 
 3 public class SetThread implements Runnable {
 4 
 5     private Student s;
 6 
 7     public SetThread(Student s) {
 8         this.s = s;
 9     }
10 
11     @Override
12     public void run() {
13         // Student s = new Student();
14         s.name = "林青霞";
15         s.age = 27;
16     }
17 
18 }
 1 package cn.itcast_03;
 2 
 3 public class GetThread implements Runnable {
 4     private Student s;
 5 
 6     public GetThread(Student s) {
 7         this.s = s;
 8     }
 9 
10     @Override
11     public void run() {
12         // Student s = new Student();//上面SetThread()类中run()方法也出现Student s = new Student(),这样就出现两个不同的对象
13         System.out.println(s.name + "---" + s.age);
14     }
15 
16 }
1 package cn.itcast_03;
2 
3 public class Student {
4     String name;
5     int age;
6 }

上面代码是有问题的,如下:

进一步改进上面代码:

 1 package cn.itcast_04;
 2 
 3 /*
 4  * 分析:
 5  *         资源类:Student    
 6  *         设置学生数据:SetThread(生产者)
 7  *         获取学生数据:GetThread(消费者)
 8  *         测试类:StudentDemo
 9  * 
10  * 问题1:按照思路写代码,发现数据每次都是:null---0
11  * 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个
12  * 如何实现呢?
13  *         在外界把这个数据创建出来,通过构造方法传递给其他的类。
14  * 
15  * 问题2:为了数据的效果好一些,我加入了循环和判断,给出不同的值,这个时候产生了新的问题
16  *         A:同一个数据出现多次
17  *         B:姓名和年龄不匹配
18  * 原因:
19  *         A:同一个数据出现多次
20  *             CPU的一点点时间片的执行权就足够你执行很多次21  *         B:姓名和年龄不匹配
22  *             线程运行的随机性
23  * 线程安全问题:
24  *         A:是否是多线程环境        是
25  *         B:是否有共享数据        是
26  *         C:是否有多条语句操作共享数据    是
27  * 解决方案:
28  *         加锁。
29  *         注意:
30  *             A:不同种类的线程都要加锁31  *             B:不同种类的线程加的锁必须是同一把32  */
33 public class StudentDemo {
34     public static void main(String[] args) {
35         //创建资源
36         Student s = new Student();
37         
38         //设置和获取的类
39         SetThread st = new SetThread(s);
40         GetThread gt = new GetThread(s);
41 
42         //线程类
43         Thread t1 = new Thread(st);
44         Thread t2 = new Thread(gt);
45 
46         //启动线程
47         t1.start();
48         t2.start();
49     }
50 }
 1 package cn.itcast_04;
 2 
 3 public class SetThread implements Runnable {
 4 
 5     private Student s;
 6     private int x = 0;
 7 
 8     public SetThread(Student s) {
 9         this.s = s;
10     }
11 
12     @Override
13     public void run() {
14         while (true) {
15             synchronized (s) {
16                 if (x % 2 == 0) {
17                     s.name = "林青霞";//刚走到这里,就被别人抢到了执行权
18                     s.age = 27;
19                 } else {
20                     s.name = "刘意"; //刚走到这里,就被别人抢到了执行权
21                     s.age = 30;
22                 }
23                 x++;
24             }
25         }
26     }
27 }

 

 1 package cn.itcast_04;
 2 
 3 public class GetThread implements Runnable {
 4     private Student s;
 5 
 6     public GetThread(Student s) {
 7         this.s = s;
 8     }
 9 
10     @Override
11     public void run() {
12         while (true) {
13             synchronized (s) {
14                 System.out.println(s.name + "---" + s.age);
15             }
16         }
17     }
18 }

 

1 package cn.itcast_04;
2 
3 public class Student {
4     String name;
5     int age;
6 }

 

原文地址:https://www.cnblogs.com/hebao0514/p/4509803.html