Android同步鎖:Synchronized的小實驗

今天在看博客的時候突然遇到了同步代碼塊——Synchronized,猛然間想到自己這次面試的時候面試官特意問了關於java線程同步鎖的問題,當時自己也是知道那麼一點單例模式,就主要聊了下單例模式,而同步代碼塊卻比較陌生,所以就 特地圍繞這點代碼塊折騰起來。
下面是這次的過程和結果,大家一起來感悟一下;

/**
 * 同步線程
 */
class SyncThread implements Runnable {

   private static int count;
   private final String TAG="SyncThread";

   public SyncThread() {
      count = 0;
      Log.d(TAG,"我執行了,count="+count);
   }

   public  void run() {
      synchronized(this) {
         for (int i = 0; i < 5; i++) {
            try {
               Log.d(TAG,Thread.currentThread().getName() + ":" + (count++));
               Thread.sleep(100);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
      }
   }
}

接下來我們就來看這段代碼的調用:

SyncThread syncThread = new SyncThread();
Thread thread1 = new Thread(syncThread, "JACK");
Thread thread2 = new Thread(syncThread, "ROSE");
thread1.start();
thread2.start();

首先來簡單分析一下這段代碼:這是一個實現了Runnable接口的類,也就是一個線程類,在這個類中有三點引起了我的注意:
第一:靜態變量count , 屬於全局變量,當頁面銷燬的時候並沒有被銷燬,這裏提一下,要注意預防內存泄漏;
第二:在這個類的構造方法中初始化了count;
第三:在線程的run方法裏面加了一把同步鎖;
第四:thread1和thread2共用一個SyncThread實例。
下面的一系列動作就圍繞着這四個特點展開了。


第一次試驗:上面的代碼不做任何更改的直接運行看看運行結果:
這裏寫圖片描述

由運行結果可以知道,JACK線程在執行的時候,synchronized會被加鎖,導致run方法就被阻塞,ROSE線程只有在JACK線程執行完成之後纔會執行;


第二次試驗:把thread1和thread2的SyncThread分別new出來,修改調用代碼如下:

SyncThread syncThread1 = new SyncThread();
SyncThread syncThread2 = new SyncThread();
Thread thread1 = new Thread(syncThread1, "JACK");
Thread thread2 = new Thread(syncThread2, "ROSE");
thread1.start();
thread2.start();

運行效果如下:
這裏寫圖片描述

首先我們不難看出,SyncThread構造方法調用了兩次,而且是連續的兩次,這個也還好理解,因爲連續構建了兩次SyncThread的對象,而後面的邏輯貌似就不正常了,明明有用到同步鎖啊,怎麼會沒有作用???


這個問題我們先留着,在第二次試驗的基礎上,進行第三次試驗,我們把同步鎖去掉看看效果,修改Runnable實現類的run方法如下:

 public  void run() {
         for (int i = 0; i < 5; i++) {
            try {
               Log.d(TAG,Thread.currentThread().getName() + ":" + (count++));
               Thread.sleep(100);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
   }

接下來我們來看看運行結果:
這裏寫圖片描述
現在只有一個地方不一樣,就是加鎖是rose然後jack,不加鎖是jack然後rose,爲了驗證這個問題是不是偶然,把代碼恢復成第二次試驗的時候,連續運行了三次都是下面的輸出:
這裏寫圖片描述
這裏就可以證明rose在前jack在後是偶然的,畢竟兩個線程是異步執行(沒有先後順序),中間的兩行長的先忽略,貌似跟本題無關,(若有關還請高人指點。。。);

那麼就剩下最後一個問題,線程加鎖在非單例模式下的運行流程是什麼???

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章