Android 死結和重入鎖,android死結

來源:互聯網
上載者:User

Android 死結和重入鎖,android死結
死結的定義:1、一般的死結一般的死結是指多個線程的執行必須同時擁有多個資源,由於不同的線程需要的資源被不同的線程佔用,最終導致僵持的狀態,這就是一般死結的定義。 

package com.cxt.thread;    public class TestDeadLock extends Thread{      boolean b;      DeadLock lock;      public TestDeadLock(boolean b, DeadLock lock) {          super();          this.b = b;          this.lock = lock;      }      public static void main(String[] args) {          DeadLock lock = new DeadLock();          TestDeadLock t1 = new TestDeadLock(true, lock);          TestDeadLock t2 = new TestDeadLock(false, lock);          t1.start();          t2.start();      }      @Override      public void run() {          if(this.b){              lock.m1();          }          else              lock.m2();      }        }    class DeadLock {      Object o1 = new Object();      Object o2 = new Object();            void m1(){          synchronized(o1){              System.out.println("m1 Lock o1 first");              synchronized(o2){                  System.out.println("m1 Lock o2 second");              }          }      }      void m2(){          synchronized(o2){              System.out.println("m2 Lock o2 first");              synchronized(o1){                  System.out.println("m2 Lock o1 second");              }          }      }  }  

 


如代碼所示我們可知:線程t1,t2都需要對象o1,o2才能正常地完成功能,但是由於他們所持的對象與要獲得的對象剛好相反,使得兩條線程一直僵持,最終導致死結。 解決方案:等其中一條線程完全執行完之後再執行另外一條線程。推廣到多條線程,按一定的順序執行多條線程。另外一種方法就是設定優先權,如果運行多條線程出現死結,優先順序低的回退,優先順序高的先執行這樣即可解決死結問題。  2、嵌套管程鎖死 
線程1獲得A對象的鎖。線程1獲得對象B的鎖(同時持有對象A的鎖)。線程1決定等待另一個線程的訊號再繼續。線程1調用B.wait(),從而釋放了B對象上的鎖,但仍然持有對象A的鎖。線程2需要同時持有對象A和對象B的鎖,才能向線程1發訊號。線程2無法獲得對象A上的鎖,因為對象A上的鎖當前正被線程1持有。線程2一直被阻塞,等待線程1釋放對象A上的鎖。線程1一直阻塞,等待線程2的訊號,因此,不會釋放對象A上的鎖,而線程2需要對象A上的鎖才能給線程1發訊號……
看代碼:
package com.cxt.Lock;    import com.cxt.thread.Synchronizer;  import com.cxt.thread.TestLock;    //lock implementation with nested monitor lockout problem  /**  * 一個坑爹的嵌套管程鎖死,區別於死結  */  public class Lock {      protected MonitorObject monitorObject = new MonitorObject();      protected boolean isLocked = false;        public static void main(String[] args) {          Lock l = new Lock();          l.isLocked = true;            MyRunnable r1 = new MyRunnable(l, 0);          MyRunnable r2 = new MyRunnable(l, 0);          Thread t1 = new Thread(r1);          Thread t2 = new Thread(r2);          t1.start();          t2.start();          /*          * 時而鎖住,時而釋放,因為另外兩條線程沒有有時捕捉不到isLocked = false          */  //      for (int i = 0; i < 100; i++) {  //          l.isLocked = false;  //          try {  //              Thread.sleep(10);  //          } catch (InterruptedException e) {  //              e.printStackTrace();  //          }  //      }          //        }        public void lock() throws InterruptedException {          // 當執行這個方法時,isLocked=true時,其他方法無論執行lock方法還是執行Unlock方法都會導致管程死結          // 只有手動將isLocked 設定為false才能解決死結,設定為false時必須讓其他線程檢測到,所以必須設定時間長一點          synchronized (this) {              while (isLocked) {                  synchronized (this.monitorObject) {                      this.monitorObject.wait();                  }              }              isLocked = true;          }      }        public void unlock() {          synchronized (this) {              this.isLocked = false;              synchronized (this.monitorObject) {                  this.monitorObject.notify();              }          }      }        static class MyRunnable implements Runnable {          Lock l = null;          int i;            public MyRunnable(Lock l, int i) {              this.l = l;              this.i = i;          }            @Override          public void run() {              try {                  if (i % 2 == 0) {                      this.l.lock();                  } else {                      this.l.unlock();                  }              } catch (InterruptedException e) {                  e.printStackTrace();              }          }        }  }  

 

  我們觀察lock()方法,執行lock()時,當isLocked 為true時,問題就來了,執行monitorObject的方法塊,但是monitorObject變成了等待狀態,但是這是外面的this鎖還是被此線程持有的,如果有其他線程要執行lock()或者unLock(),此時都會產生無限等待的狀態,此線程也因此永遠處於無限帶等待其他線程來喚醒monitorObject的狀態,最終就一直僵持著。 解決方案手動將isLocked設為false. 這一種較坑,編代碼時別沒事找事做。 3、重入鎖死
package com.cxt.Lock;    public class Lock2{      private boolean isLocked = false;            public static void main(String[] args) {          Lock2 lock = new Lock2();                    MyRunnable r1 = new MyRunnable(lock, true);          MyRunnable r2 = new MyRunnable(lock, false);          Thread t1 = new Thread(r1);          Thread t2 = new Thread(r2);          t1.start();            //      t2.start();      }      public synchronized void lock()          throws InterruptedException{          while(isLocked){              wait();          }          isLocked = true;      }        public synchronized void unlock(){          isLocked = false;          notify();      }            static class MyRunnable implements Runnable{          Lock2 l = null;          boolean flag = false;          public MyRunnable(Lock2 l, boolean flag) {              this.l = l;              this.flag = flag;          }          @Override          public void run() {              if(flag == true)                  try {  //                  如果連續執行兩次lock(),就會產生系統無限等待的狀態  //                  解決方案就是在兩次中間執行一次unLock()方法                      l.lock();                      System.out.println("Lock!");  //                  l.unlock();  //                  System.out.println("Unlock!");                      l.lock();                      System.out.println("Lock!");                  } catch (InterruptedException e) {                      e.printStackTrace();                  }              else                   l.unlock();          }                }  }  

 


當連續執行兩次lock()時會出現:第一次,isLocked為false,執行完把isLocked設為true.第二次,isLocked為true,此時就會處於無限等待的狀態。 解決方案,兩個lock()中間執行一次unLock方法,或者由另外一條線程來執行一次unLock()方法。                        【重入鎖】
package com.text;public class Lock2{      private boolean isLocked = false;            public static void main(String[] args) {          Lock2 lock = new Lock2();                    MyRunnable r1 = new MyRunnable(lock, true);          MyRunnable r2 = new MyRunnable(lock, false);          Thread t1 = new Thread(r1);          Thread t2 = new Thread(r2);          t1.start();            //      t2.start();      }      public synchronized void lock()          throws InterruptedException{          while(isLocked){            System.out.println("synchronized wait()!");              unlock();            wait();          }          isLocked = true;          System.out.println("synchronized lock!");      }        public synchronized void unlock(){          isLocked = false;          notify();          System.out.println("synchronized unlock!");      }            static class MyRunnable implements Runnable{          Lock2 l = null;          boolean flag = false;          public MyRunnable(Lock2 l, boolean flag) {              this.l = l;              this.flag = flag;          }          @Override          public void run() {              if(flag == true)                  try {  //                  如果連續執行兩次lock(),就會產生系統無限等待的狀態  //                  解決方案就是在兩次中間執行一次unLock()方法                      l.lock();                      System.out.println("Lock!");                      l.lock(); //                  l.unlock(); //注釋了                    System.out.println("Lock!");                  } catch (InterruptedException e) {                      e.printStackTrace();                  }              else                   l.unlock();          }                }  }  

輸出:

synchronized lock!
Lock!
synchronized wait()!
synchronized unlock!

在一個synchronized方法/塊的內部調用本類的其他synchronized方法/塊時,是永遠可以獲得鎖的。

 

 

 

 

package com.text;public class Lock2{      private boolean isLocked = false;            public static void main(String[] args) {          Lock2 lock = new Lock2();                    MyRunnable r1 = new MyRunnable(lock, true);          MyRunnable r2 = new MyRunnable(lock, false);          Thread t1 = new Thread(r1);          Thread t2 = new Thread(r2);          t1.start();            //      t2.start();      }      public synchronized void lock()          throws InterruptedException{          while(isLocked){            System.out.println("synchronized wait()!");              wait();          }          isLocked = true;          System.out.println("synchronized lock!");      }        public synchronized void unlock(){          isLocked = false;          notify();          System.out.println("synchronized unlock!");      }            static class MyRunnable implements Runnable{          Lock2 l = null;          boolean flag = false;          public MyRunnable(Lock2 l, boolean flag) {              this.l = l;              this.flag = flag;          }          @Override          public void run() {              if(flag == true)                  try {  //                  如果連續執行兩次lock(),就會產生系統無限等待的狀態  //                  解決方案就是在兩次中間執行一次unLock()方法                      l.lock();                      System.out.println("Lock!");                      l.lock();                     l.unlock(); //取消注釋了                    System.out.println("Lock!");                  } catch (InterruptedException e) {                      e.printStackTrace();                  }              else                   l.unlock();          }                }  }  

輸出:

synchronized lock!
Lock!
synchronized wait()!

因為連續兩個lock方法,導致在第二次時形成死結,第三次的unlock由於不是在synchronized方法/塊內調用的,所以無法擷取鎖,

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.