zkzk7410
2017-04-22 15:15
采纳率: 68.8%
浏览 818
已采纳

『初学请教』Java线程同步问题

请教大虾线程问题,如下代码:
package com.test;

public class Timer {

private static int num = 0;

public synchronized void add(String name) {
    num++;
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println(name + "是第" + num + "个访问的用户");
}

}

package com.test;

public class TestSync implements Runnable {

private Timer t = new Timer();

public void run() {
    t.add(Thread.currentThread().getName());
}

}

package com.test;

public class test {

/**
 * @param args
 */
public static void main(String[] args) {
    Thread t1=new Thread(new TestSync());
    Thread t2=new Thread(new TestSync());
    t1.setName("t1");
    t2.setName("t2");
    t1.start();
    t2.start();
}

}

输出的结果一直是:
t1是第2个访问的用户
t2是第2个访问的用户


疑问: 明明已经给 Timer类的add方法加了synchronized, 为么结果都是显示是第2个访问的用户

请求大神指点,小弟在此谢过!

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

4条回答 默认 最新

  • weixin_38388710 2017-04-22 15:46
    已采纳

    流程分析:首先主线程执行并开启两个线程t1、t2,接下来就是三个线程争抢CPU控制权,假设t1获得控制权,t1线程新建一个timer对象并调用其add方法(这时add方法用的是此timer对象锁,还有忘记说了mun+1),然后t1线程睡眠一秒,其他线程获得控制权,假设t2线程获得控制权,t2线程又创建一个timer对象并调用add方法(此时add方法的锁改为t2timer的锁,mun又加一次1,此时mun为2),接下来自己分析。手打不易不喜勿喷。

    已采纳该答案
    打赏 评论
  • weixin_38388710 2017-04-22 15:28

    这结果没错啊,只可意会不可言传,有两把锁,线程默认使用的是对象锁(你这里有两个timer对象了),将锁改成累级别的锁,即可得到你想要的结果。手打不易不喜勿喷。

    打赏 评论
  • zkzk7410 2017-04-23 01:05

    public class Timer {

    private static int num = 0;
    
    public void add(String name) {
        synchronized (Timer.class) {   // 类级别锁
            num++;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(name + "是第" + num + "个访问的用户");
        }
    }
    

    }

    打赏 评论
  • KevinDai007 2017-04-24 10:14

    用同一个对象加锁就好了,一般情况少用类锁

            TestSync test = new TestSync();
            Thread t1=new Thread(test);
        Thread t2=new Thread(test);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();
    
    打赏 评论

相关推荐 更多相似问题