• 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 }

     

  • 相关阅读:
    明星球队的傲慢
    VS2010测试方面的文章重点
    项目管理有感
    团队从小到大,再到体验团队
    css实现文字渐变
    echarts坐标轴文字过长省略
    mustache+mock
    你有选择的权利
    呵呵,初学者小编
    Centos7升级到OpenSSH_8.8p1、OpenSSL 1.1.1l版本
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4509803.html
Copyright © 2020-2023  润新知