JAVA基础之多线程三期--线程安全问题

一、线程安全问题就是指:多个线程并发访问同一个资源而发生安全性的问题,
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写 操作,一般来说,这个全局变量是线程安全的;
若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全。

问题出现:

public class ThreadSafe implements Runnable {
   private int ticket = 100;

/**
 * 执行买票
 */
public void run() {
  while (true){
      if(ticket>0){
          //提高线程安全问题出现概率,让他睡眠
          try {
              Thread.sleep(10);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          System.out.println(Thread.currentThread().getName()+" 正在卖第:"+ticket+"票");
          ticket--;
        }
     }
   }}

   public class ThreadSafeTest {
      public static void main(String[] args) {
          //创建target目标实现类
          ThreadSafe threadSafe = new ThreadSafe();
          //开启三个线程窗口,必须三个线程实例对象共享一个目标对象,才能保证票数就三百张
          Thread th1 = new Thread(threadSafe,"窗口一");
          Thread th2 = new Thread(threadSafe,"窗口二");
          Thread th3 = new Thread(threadSafe,"窗口三");
              th1.start();
              th2.start();
              th3.start();
          }
       }

二、窗口1线程进入操作的时候,窗口2和窗口3线程只能在外等着,窗口1操作结束,窗口1和窗口2和窗口3才有机会进入代码 去执行。也就是说在某个线程修改共享资源的时候,其他线程不能修改该资源,等待修改完毕同步之后,才能去抢夺CPU 资源,完成对应的操作,保证了数据的同步性,解决了线程不安全的现象

三、引用同步机制解决线程安全问题
1. 同步代码块。 2. 同步方法。 3. 锁机制

  A、同步代码块
        格式:
              synchronized(同步锁){      
                    需要同步操作的代码
              }


        同步锁: 对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁. 
              1. 锁对象 可以是任意类型。 
              2. 多个线程对象  要使用同一把锁  
              3. 锁对象的作用:把同步代码块锁住,只允许一个线程在同步代码块上执行

     
      测试:
           
         public class ThreadSafe implements Runnable {
            private int ticket = 100;
            Object obj = new  Object();
            /**
             * 执行买票
             */
            public void run() {
               while (true){
                 synchronized (obj){
                     if(ticket>0){
                   //提高线程安全问题出现概率,让他睡眠
                     try {
                        Thread.sleep(10);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                   }
                   System.out.println(Thread.currentThread().getName()+" 正在卖第:"+ticket+"票");
                      ticket--;
                 }
             }
          }
       }
   }

   3. Lock(锁)
         Lock锁也称同步锁,加锁与释放锁方法化了,如下:
              public void lock() :加同步锁。 
              public void unlock() :释放同步锁 
        使用步骤:
              1.在成员变量位置创建一个ReentrantLock()对象;
              2.在可能出现安全问题的代码前调用Lock接口中的方法lock()   
              3.在可能出现安全问题的代码后调用Lock接口中的方法unlock()  

        
      public class ThreadSafe1 implements Runnable {
            private int ticket = 100;
            Lock lock = new ReentrantLock();
       /**
        * 执行买票
        */
       public void run() {
            while (true){
              lock.lock();
              if(ticket>0){
                //提高线程安全问题出现概率,让他睡眠
            try {
              Thread.sleep(10);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
              System.out.println(Thread.currentThread().getName()+" 正在卖第:"+ticket+"票");
              ticket--;
        }
            lock.unlock();
        }
      }
  }
posted @ 2020-07-22 01:06  jock_javaEE  阅读(162)  评论(0编辑  收藏  举报