java11_線程的同步

線程的同步---以三個窗口售票100張爲例

(1)問題:賣票的過程出現重票和錯票
(2)緣由:當某個線程操做車票的過程當中,還沒有操做完成,其餘線程參與進來,也操做車票
(3)解決:當一個線程a在操做共享對象時,其餘線程不能參與進來,直到線程a操做完畢,其餘
線程才能夠開始操做共享對象。
這種狀況,即便線程a出現了阻塞,也不能被改變
(4)java中經過同步機制,來解決線程的安全問題:java

方式一:同步代碼塊

synchronized(同步監視器){
 //須要被同步的代碼(操做共享數據的代碼)
//共享數據:多個線程共同操做的變量
//不能包含太多,不也能包太少
 }

同步監視器----俗稱:鎖,任何一個類的對象,均可以充當鎖
要求:多個線程必需要共用同一把鎖,惟一性
補充1:在實現Runnable接口中,使用this作同步監視器 安全

class Window1 implements Runnable {
      /*只創造了一個Window1對象,所以能夠實現100張票共享*/
      private int ticket=100;
      Object ob=new Object();//任何一個類的對象,均可以充當鎖
    @Override
    public void run() {
        while(true){
            synchronized(this) {//此時的this:惟一的window1對象,不用在另外建立一個類的對象
            // synchronized(ob) {
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + "賣票:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

補充2:在繼承Thread類建立多線程的方式中,使用 線程類.class 做爲同步監視器,慎用this多線程

class Window2 extends Thread{
        private static int ticket=100;
        private static Object obj=new Object();
        @Override
        public void run(){
            while(true) {
             // synchronized (obj) {
                synchronized (Window2.class) {//類類型的對象也能夠
             // synchronized(this) {錯誤,在繼承這種方法的時候不能寫this,由於new的時候會產生多個對象
                try {
                    Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                if (ticket > 0) {
                    System.out.println(getName() + "賣票:" + ticket);
                    ticket--;
                    }
                }
            }
        }
    }
}

方式二:同步方法

將須要進行同步的代碼放在一個方法中,給方法加上synchronized
關於同步方法的總結:
①同步方法仍然涉及到同步監視器,只是不須要顯示聲明
②非靜態的同步方法:同步監視器是:this
靜態的同步方法:同步監視器是當前類的自己 類.classide

1.用同步方法解決,實現Runnable接口建立多線程 this

class Window3 implements Runnable {
   /*只創造了一個Window1對象,所以能夠實現100張票共享*/
        private int ticket=100;
        @Override
        public void run() {
            while(true){
                show();
            }
        }

        private synchronized void show(){
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "賣票:" + ticket);
                ticket--;
        }
    }
}

2.同步方法解決繼承Thread類建立多線程 線程

class Window4 extends Thread{
            private static int ticket=100;
            @Override
            public void run(){
                   while(true) {
                        show();
                    }
            }

            private static synchronized void show(){//此時同步監視器:Window4.class
            //private synchronized void show(){//同步監視器的對象不惟一,和new 有關
            if (ticket > 0) {
                 try {
                        Thread.sleep(100);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "賣票:" + ticket);
                ticket--;
          }
     }
}

使用同步機制的做用:

好處----同步的方式,解決了線程的安全問題
侷限性----操做同步代碼時,只能有一個線程參與,其餘線程等待。至關因而一個單線程的過程,效率低code

相關文章
相關標籤/搜索