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 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示