第37节:多线程安全问题

作者: 魔王哪吒 | 来源:发表于2018-09-03 18:03 被阅读58次
    标题图

    定义用户去银行存钱,每次存100,存3次

    class Bank {
     // 总数
     private int sum;
    // 定义方法
     public void add(int num){
      // 传入参数
      sum = sum + sum;
     // 加后的值
      System.out.println("sum"+sum);
     }
    }
    
    class Demo implements Runnable{
     // 定义银行类对象,创建实例对象
     private Bank  b = new Bank();
    // 线程run()
     public void run(){
      for(int x=0; x<3; x++){
       // 将参数放入对象方法中
       b.add(100)
      }
     }
    }
    
    // 测试类
    class Test{
     public static void main(String[] args){h
      // 创建对象
      Demo d=new Demo();
     // 创建线程对象
      Thread t1 = new Thread(d);
      Thread t2 = new Thread(d);
     // 线程开启
      t1.start();
      t2.start();
    }
    }
    

    如果出现这个代码,出现了多线程安全问题。共性数据即共享对象中的数据。

    class Bank {
     // 总数
     private int sum;
    // 创建对象
     private Object obj = new Object();
    // 定义方法
     public void add(int num){
      synchronized(obj){
      // 传入参数
      sum = sum + sum;
     // 加后的值
      System.out.println("sum"+sum);
     }
     }
    }
    

    安全问题,加了同步可以解决数据安全。

    class Tickets implements Runnable{
     private int tickets = 100;
     private Object obj = new Object();
     public void run(){
      whilt(true){
       synchronized(obj){
        if(tickets>0){
         try{
          Thread.sleep(1000);
         }catch(Exception e){
          System.out.println(Thread.currentThread().getName()+tickets);
         }
        }
       }
      }
     }
    }
    

    饿汉式

    class Single{
     private static final Single s = new Single();
     private Single(){)
     public static Single getInstance(){
      return s;
     }
    }
    

    懒汉式

    class Single{
     private static Single s = null;
     private Single(){}
     public static Single getInstance(){
      if(s==null){
       s = new Single();
      }
     return s;
     }
    }
    

    多线程

    在同一时间,做多件事情.

    创建线程的方法
    继承类Thread并重写run(),run()称为线程体;用这种方法定义的类不能再继承其他类。

    class FirstThread extends Thread{
    public void run(){
     for(int i=0;i<100;i++){
      System.out.println("FirstThread"+i);
     }
    }
    }
    
    class Test{
    public static void main(Sting args[]){
     FirstThread ft = new FirstThread();
     ft.start();
     
     for(int i = 0; i<100;i++){
      System.out.println("main"+i):
     }
    }
    }
    

    接口Runnable的类作为线程的目标对象

    class Test implements Runnable{
    public void run(){
     for(int i = 0;i<100;i++){
      System.out.println("Runnable"+i);
     }
    }
    }
    
    class Test{
    public static void main(String args[]){
     Test test = new Test();
     Thread t = new Thread(test);
     System.out.println(t.getPriority());
     t.start();
    }
    }
    

    唤醒线程

    线程类


    image.png

    主方法类


    image.png

    线程同步与等待

    image.png

    线程的同步

    关键字synchronized

    多线程就是调用这个synchronized的方法的,
    当线程用了这个方法,那么其他线程想使用这个方法时就得等,直到线程使用完该调用的方法。

    同步中的等待

    wait()方法:暂时让出cpu;
    notifyAll()方法:等待结束。

    线程是程序中的执行线程,在Java虚拟机中允许应用程序并发地运行多个执行线程,每个线程独有它自己的一个优先级,高的优先级的执行线程优先于低优先级的线程,每个线程都可以有或者不可以标记的一个守护程序。当一个线程中的运行代码创建一个Thread对象的时候,该线程的初始化优先级就被设定,只有创建线程是守护线程的时候,这个线程才是守护程序。

    在Java中的虚拟机启动,通常会有单个非守护线程,一般在代码中有个线程为主线程,main方法。

    第36节:Java当中的线程
    第35节:Java面向对象中的多线程

    这两篇文章讲了什么是进程,什么是线程等一些概念。

    进程要执行需要依赖线程,线程是进程中最小的执行单位,一个进程中至少要有一个线程,在线程中串行是单条线程来执行多个任务来说的,任务A到任务B到任务C,只有任务A完成了后才开始到任务B,一条线完成。并行为开启多个线程同时进行任务,同一时刻发生任务A,任务B,任务C。

    什么是线程安全

    线程出现问题是在多线程的情况之下产生的。出现线程安全问题,如何去解决这个问题呢?用synchronized关键字,用来控制线程同步的,可以让线程在多线程的情况下,不被多个线程同时执行,保证我们数据的安全性。

    public synchronized void add(int i){
     ...
    }
    

    Lock的引入让锁有了可操作性,它是在Java1.6被引入进来的,Lock可以去手动获取锁和释放锁。

    // ReentrantLock是Lock的子类
    private Lock lock = new ReentrantLock(); 
    
    private void methodThread(Thread thread){
           // 获取锁对象
           lock.lock(); 
           try {
               System.out.println(thread.getName() + "获得了锁");
           }catch(Exception e){
               e.printStackTrace();
           } finally {
               System.out.println(thread.getName() + "释放了锁");
               // 释放锁对象
               lock.unlock(); 
           }
    }
    

    往后余生,努力学习
    简书作者:达叔小生
    90后帅气小伙,爱编程,爱运营,爱折腾。
    简书博客: https://www.jianshu.com/u/c785ece603d1

    结语

    • 下面我将继续对其他知识 深入讲解 ,有兴趣可以继续关注
    • 小礼物走一走 or 点赞

    相关文章

      网友评论

        本文标题:第37节:多线程安全问题

        本文链接:https://www.haomeiwen.com/subject/qrgvwftx.html