程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> java-Java 多線程問題 synchronized(obj)的疑惑

java-Java 多線程問題 synchronized(obj)的疑惑

編輯:編程綜合問答
Java 多線程問題 synchronized(obj)的疑惑

是這樣的,我想知道synchronized(obj)的用法,然後寫了如下的代碼,運行結果我如何都搞不清,還請各位指點。

代碼1:

 public class MyObj 
{
    private Integer a;
    private Double b;
    private Integer c;

    public void setA()
    {
        System.out.println(Thread.currentThread().getName() + "搶到鎖..setA");
        synchronized(c)
        {
            System.out.println("    " + Thread.currentThread().getName() + " " + this.a + "  " + this.b);
            this.a = 1;
            this.b = 2.0;
            try{
                Thread.sleep(200);//(int) (Math.random()*2000)
            }catch(InterruptedException e)          {
                e.printStackTrace();
            }
            System.out.println("   " + Thread.currentThread().getName() + " " + this.a + "  " + this.b);
        }
    }
    public void setB()
    {
        System.out.println(Thread.currentThread().getName() + "搶到鎖....setB");
        synchronized(c)
        {
            System.out.println("    " + Thread.currentThread().getName() + " " + this.a + "  " + this.b);
            this.a = 3;
            this.b = 4.0;
            try{
                Thread.sleep(200);//(int) (Math.random()*2000)
            }catch(InterruptedException e)          {
                e.printStackTrace();
            }
            System.out.println("    " + Thread.currentThread().getName() + " " + this.a + " " + this.b);
        }
    }
    public MyObj()
    {
        this.a = -1;
        this.b = -1.0;
        this.c = 0;
    }
}

代碼2:

 public class Change 
{
    private MyObj myObj;

    public Change(MyObj myObj)
    {
        this.myObj = myObj;
    }

    public static void main(String args[])
    {
        final MyObj myObj = new MyObj();
        final Integer a = 1;

        Thread thread1 = new Thread(new Runnable(){
            public void run()
            {
                for(int product = 1; product <= 3; ++product)
                {
                    try{
                        Thread.sleep((int) (Math.random()*200));//(int) (Math.random()*2000)
                        myObj.setA();
                    }catch(InterruptedException e)
                    {
                        e.printStackTrace();
                    }

                }
            }
        },"thread1");

        Thread thread2 = new Thread(new Runnable(){
            public void run()
            {
                for(int product = 1; product <= 3; ++product)
                {
                    try{
                        Thread.sleep((int) (Math.random()*200));//(int) (Math.random()*2000)
                        myObj.setB();
                    }catch(InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        },"thread2");

        thread1.start();
        thread2.start();

    }
}

輸出結果(之一):
thread2搶到鎖....setB
thread2 -1 -1.0
thread1搶到鎖..setA
thread2 3 4.0
thread1 3 4.0
thread2搶到鎖....setB
thread1 1 2.0
thread2 1 2.0
thread1搶到鎖..setA
thread2 3 4.0
thread1 3 4.0
thread2搶到鎖....setB
thread1 1 2.0
thread2 1 2.0
thread1搶到鎖..setA
thread2 3 4.0
thread1 3 4.0
thread1 1 2.0

**  但是**,如果將 
 System.out.println(Thread.currentThread().getName() + "搶到鎖....setA");
 和
 System.out.println(Thread.currentThread().getName() + "搶到鎖....setB");

放到 synchronized(c) 塊裡面,那麼結果之一:
thread1搶到鎖..setA
thread1 -1 -1.0
thread1 1 2.0
thread2搶到鎖....setB
thread2 1 2.0
thread2 3 4.0
thread1搶到鎖..setA
thread1 3 4.0
thread1 1 2.0
thread2搶到鎖....setB
thread2 1 2.0
thread2 3 4.0
thread1搶到鎖..setA
thread1 3 4.0
thread1 1 2.0
thread2搶到鎖....setB
thread2 1 2.0
thread2 3 4.0

可能 輸出有先後,但是 至少 thread1,thread2的輸出之間,不會相互干擾。。。

我仔細觀察了,上面的結果,雖然相互干擾,但是也不會出錯,但是為什麼 會這樣呢? 既然 已經進入 thread1了,thread2怎麼還能得到鎖呢。。如果這樣的話,synchronized(obj)還有啥意思啊(obj不一定是this)? 。實在沒搞懂啊。再次麻煩各位幫忙。

總共就1個幣,諒解哈。

最佳回答:


還是強調下面這種寫法,在打印“搶到鎖”時,實際不一定搶到鎖了,因為日志是在synchronized前面打印的,只有在內部打印才是確實搶到鎖~:
public void setB()
{
System.out.println(Thread.currentThread().getName() + "搶到鎖....setB");
synchronized(c)
{

這樣是不是容易理解點:
thread2搶到鎖....setB ----進入thread2,明確這裡不是同步塊,不受synchronized影響
thread2 -1 -1.0 -----thread2獲得鎖,這是同步塊裡面第一句日志,確定是獲取到鎖了
thread1搶到鎖..setA -----進入thread1
thread2 3 4.0 -----thread2釋放鎖,這是同步塊最後一句日志,打完就可以認為是釋放鎖了
thread1 3 4.0 -----thread1獲得鎖
thread2搶到鎖....setB -----進入thread2
thread1 1 2.0 -----thread1釋放鎖
thread2 1 2.0
thread1搶到鎖..setA
thread2 3 4.0
thread1 3 4.0
thread2搶到鎖....setB
thread1 1 2.0
thread2 1 2.0
thread1搶到鎖..setA
thread2 3 4.0
thread1 3 4.0
thread1 1 2.0

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved