• 多线程--毕向东java基础教程视频学习笔记


    目录

    1.多线程运行的安全问题

    2.多线程同步代码块

    3.同步方法的锁是this

    4.静态同步方法的锁是Class对象

    5.单例设计模式(面试中的考点)

    6.死锁(一个发生死锁的例子)

    多线程运行的安全问题

    例子:售票系统

     1 class Ticket implements Runnable
     2 {
     3     //定义静态变量ticket
     4     private static int ticket=100;
     5     public void run()
     6     {
     7         while(true)
     8         {
     9             //判断票编号是否大于0
    10             if(ticket>0)
    11             {
    12                 try
    13                 {
    14                     Thread.sleep(10);
    15                 }
    16                 catch (InterruptedException ie)
    17                 {
    18                     System.err.println("Error:"+ie);
    19                 }
    20                 System.out.println(Thread.currentThread().getName()+"--sale:"+ticket--);
    21             }
    22         }
    23     }
    24 
    25 }
    26 public class ThreadDemo
    27 {
    28     
    29     public static void main(String[] args)
    30     {
    31         //创建一个实现了Runnable接口的Ticket对象
    32         Ticket t=new Ticket();
    33         //创建4个线程
    34         Thread t1=new Thread(t);
    35         Thread t2=new Thread(t);
    36         Thread t3=new Thread(t);
    37         Thread t4=new Thread(t);
    38         //分别启动4个线程
    39         t1.start();
    40         t2.start();
    41         t3.start();
    42         t4.start();
    43 
    44     }
    45 }

    运行:

    最后,打印出了了“0,-1,-2”的错票情况(票的编号从1-100).多线程出现安全问题。

     

    问题的原因:

    当多条语句在操作用一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,

    另一个数据参与进来执行,造成共享数据的错误。

    解决方法:

    对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中不允许其他线程参与进来。

    java对于多线程的同步提供了专业的解决方法,就是同步代码块。

    多线程同步代码块

    synchronized(对象)

    {需要被同步的代码块}

    对象如同锁,持有锁的线程可以在同步代码块中执行,

    没有持有锁的线程即使获得CPU的执行权也进不去,因为没有获取锁。

     

    例子:火车上的卫生间。

    同步的前提:

    1.必须要有两个或者两个以上的线程。

    2.必须是多个线程使用同一把锁。

     

    好处:解决了多线程的安全问题。

    弊端:需要判断锁,较为消耗资源。

     一般不可以把run()方法全放在同步代码块中,否则就是单线程了。

    同步方法:

    银行
    有两个储户,分别存300元,每次存100元,存3次
    目的:该线程是否有安全问题,如果有,如何解决?

    如何找问题:
    1.明确哪些代码是多线程运行代码
    2.明确共享数据
    3.明确多线程运行代码中哪些代码操作共享数据的。

     1 class Bank
     2 {
     3     //定义sum,代表银行的总金额
     4     private int sum;
     5     Object obj=new Object();
     6     public void add(int n)
     7     {
     8         
     9         //sum为共享数据,对sum有两句操作,
    10         //防止出现不安全问题,使用同步代码块
    11         synchronized(obj)
    12         {
    13             sum=sum+n;
    14             try
    15             {
    16                 Thread.sleep(10);
    17             }
    18             catch (InterruptedException ie)
    19             {
    20                 System.err.println("Error:"+ie);
    21             }
    22             System.out.println("sum="+sum);
    23         }
    24     }
    25 }
    26 class Cus implements Runnable
    27 {
    28     private Bank b=new Bank();
    29     //存三次
    30     public void run()
    31     {
    32         for(int i=0;i<3;i++)
    33             b.add(100);
    34     }
    35 }
    36 public class BankDemo
    37 {
    38     public static void main(String[] args)
    39     {
    40         Cus cus=new Cus();
    41         //创建两个线程,代表2个储户的存钱过程
    42         Thread t1=new Thread(cus);
    43         Thread t2=new Thread(cus);
    44         t1.start();
    45         t2.start();
    46     }
    47 }

    注:同步的两种表现形式:a.同步代码块   b.同步函数

    同步方法的锁是this

    同步方法用的是哪一个锁呢?

    方法需要被对象调用,那么方法都有一个所属对象的引用,就是this。

    所以同步方法的锁就是this。

    静态同步方法的锁是Class对象

    当同步方法被静态修饰后,使用的锁就不是this了,因为静态方法中不可以使用this。

    静态方法进内存时,内存没有本类对象,但一定有该类对应的字节码文件对象。

    类名.class。该对象的类型是Class。

    静态同步方法,使用的锁是该方法所在的类的字节码文件对象。类名.class

    单例设计模式

    1.饿汉式

    1 class Single
    2 {
    3     private static final Single s=new Single();
    4     private Single(){}
    5     public static Single getInstance()
    6     {
    7         return s;
    8     }
    9 }

    2.懒汉式:

     1 /*
     2 面试时的考点:
     3 
     4 懒汉式的特点:实例的延迟加载
     5 会出现的问题:多线程访问时会出现安全问题
     6 解决方法:用同步方法或者同步代码块都行,
     7 但是有些低效,可以通过双重判断,减少判断锁的次数,稍微提高效率。
     8 加同步时候:使用的锁是该类的字节码对象
     9 
    10 */
    11 class Single
    12 {
    13     private static  Single s=null;
    14     private Single(){}
    15     public static Single getInstance()
    16     {
    17         //通过双重判断,减少判断锁的次数,稍微提高效率。
    18         if (s==null)
    19         {
    20             synchronized (Single.class)
    21             {
    22                 if(s==null)
    23                     s=new Single();
    24             }
    25         }
    26         return s;
    27     }
    28 }

    死锁:同步中嵌套同步

    死锁的例子

     1 class Test implements Runnable
     2 {
     3     private boolean flag;
     4     Test(boolean _flag)
     5     {
     6         flag=_flag;
     7     }
     8     public void run()
     9     {
    10         if(flag)
    11         {
    12             synchronized(MyLock.locka)
    13             {
    14                 System.out.println("if locka");
    15                 synchronized(MyLock.lockb)
    16              {
    17                     System.out.println("if lockb");
    18 
    19              }
    20 
    21             }
    22 
    23         }
    24         else
    25         {
    26             synchronized(MyLock.lockb)
    27             {
    28                 System.out.println("else lockb");
    29                 synchronized(MyLock.locka)
    30              {
    31                     System.out.println("else locka");
    32 
    33              }
    34 
    35             }
    36 
    37         }
    38 
    39     }
    40 }
    41 class MyLock
    42 {
    43     static Object locka=new Object();
    44     static Object lockb=new Object();
    45 }
    46 public class DeadLockTest
    47 {
    48     public static void main(String[] args)
    49     {
    50         Thread t1=new Thread(new Test(true));
    51         Thread t2=new Thread(new Test(false));
    52         t1.start();
    53         t2.start();
    54 
    55     }
    56     
    57 }
  • 相关阅读:
    搜狗输入法招聘数据挖掘、自然语言处理实习生
    python 备忘
    从零开始
    [转]随笔
    重学python
    关于tensorflow conv2d卷积备忘的一点理解
    python args kwargs 传递参数的区别
    something backup
    R语言命令汇总
    newwork setup
  • 原文地址:https://www.cnblogs.com/wsw-tcsygrwfqd/p/4988988.html
Copyright © 2020-2023  润新知