java同步和互斥程式說明(一)

來源:互聯網
上載者:User

         所有對象都自動含有單一的鎖,也就是所有對象都有且只有唯一的鎖,所以當某個任務(線程)訪問一個類A中含有sycnhronized的方法是,那麼在這個線程從該方法返回之前(也就是該方法在當前線程執行完之前),類A中的其他被該關鍵字標記的方法在其他的線程中都會被阻塞。
            通俗點說就是,當調用A的含有synchronized的方法是,A會被枷鎖,此時A中其他含有synchronized方法只有等到前一個方法調用完畢釋放了鎖才能被調用

           具體說明見另一篇部落格<<java同步和互斥》

        下面看看具體的程式,其中,Timer中的欄位num是共用資源

       

public class TestSync implements Runnable {  Timer timer = new Timer();   public static void main(String[] args) {    TestSync test = new TestSync();    Thread t1 = new Thread(test);    Thread t2 = new Thread(test);    t1.setName("t1");     t2.setName("t2");    t1.start();     t2.start();  }  public void run(){    timer.add(Thread.currentThread().getName());  }}class Timer{  private static int num = 0;  public  void add(String name){       num ++;    try {Thread.sleep(1);}     catch (InterruptedException e) {}    System.out.println(name+", 你是第"+num+"個使用timer的線程");    }}

由於沒有同步,所以運行結果如下所示

t1, 你是第2個使用timer的線程

t2, 你是第2個使用timer的線程

也就是說當線程一運行到num++的時候被打線程2打斷了,由於java中遞增和遞減操作均不是原子操作,所以本程式中即使沒有調用sleep,也會出現這種被打斷的情況

下面看看同步的效果

 public void add(String name) {        synchronized (this) {//同步            num++;            try {                Thread.sleep(1000);            } catch (InterruptedException e) {            }            System.out.println(name + ", 你是第" + num + "個使用timer的線程");        }    }

這樣運行結果就會出是正確的

t1, 你是第1個使用timer的線程

t2, 你是第2個使用timer的線程

但是,下面為了說明問題把TestSync裡面的run方法改成如下所示

 public void run() {//                   time.add(Thread.currentThread().getName());            try {                Thread.sleep(1000);//為了顯示結果,讓其睡眠一秒            } catch (InterruptedException ex) {                Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);            }          System.out.println(Thread.currentThread().getName() + "----");        }

那麼在此運行就是

t1, 你是第1個使用timer的線程

t2, 你是第2個使用timer的線程

t1--------

t2--------

而不是你所想象的

t1, 你是第1個使用timer的線程
t1----
t2, 你是第2個使用timer的線程
t2----

原因就是線上程t1在睡眠的時候,線程t2切換進來,執行了一次,怎樣得到正確的結果呢,下面把TestSync裡面的run方法做如下改進就可以得到上面預期的結果

 public void run() {       synchronized(time){            time.add(Thread.currentThread().getName());            try {                Thread.sleep(3000);            } catch (InterruptedException ex) {                Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);            }          System.out.println(Thread.currentThread().getName() + "----");        }    }

因為t1先獲得time的鎖,所以在執行完run裡面的同步塊之前,即使sleep(),t2也不會執行,因為t2沒有獲得time的鎖,且sleep()操作也不釋放鎖(這也是和wait的巨大區別)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.