Guimashisqll 2015-07-30 20:11 采纳率: 50%
浏览 1708
已采纳

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个币,谅解哈。

  • 写回答

6条回答 默认 最新

  • fanst_ 2015-07-31 14:55
    关注

    还是强调下面这种写法,在打印“抢到锁”时,实际不一定抢到锁了,因为日志是在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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

悬赏问题

  • ¥15 esp8266控制共阳极wrgb灯板无法关闭所有led灯
  • ¥100 python读取速度问题
  • ¥15 stm32f407使用DMA问题
  • ¥15 您好 这个API接口该怎么弄 网站搭建好了 API也有 现在就不知道该怎么填写API 不知道怎么用
  • ¥88 用uniapp写一个多端的程序,用到高德地图,用高德的JSAPI吗?
  • ¥20 关于#c++#的问题:水果店管理系统
  • ¥30 dbLinq最新版linq sqlite
  • ¥20 对D盘进行分盘之前没有将visual studio2022卸载掉,现在该如何下载回来
  • ¥15 完成虚拟机环境配置,还有安装kettle
  • ¥15 有人会搭建生鲜配送自营+平台的管理系统吗