A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 史卜坤 中级黑马   /  2012-6-29 08:26  /  1720 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

public class A implements Runnable {
        public static void main(String[] args) {
                A a = new A();
                Thread t1 = new Thread(a);
                Thread t2 = new Thread(a);
                Thread t3 = new Thread(a);
                t1.start();
                t2.start();
                t3.start();
        }

        Integer i = 100;
        //Object o = new Object();
        public void run() {
                while (true)
                {
                        synchronized (i) {
                                if (i>0)
                                {
                                        try {
                                                Thread.sleep(20);
                                        } catch (Exception e) {
                                                e.printStackTrace();
                                        }
                                        System.out.println(Thread.currentThread().getName()+" == "+i--);
                                }
                        }
                }
        }
}

我要使变量i 多线程同步,这个代码为什么不可以,synchronized () {}  这个括号里头不是可以是任意对象吗?

评分

参与人数 1技术分 +2 收起 理由
刘蕴学 + 2 常见的同步错误

查看全部评分

4 个回复

倒序浏览
本帖最后由 李天甲 于 2012-6-29 08:48 编辑

这么看来是有问题,刚才没看出来....
调试了一下你会发现
i--的过程改变了i对象的引用...
回复 使用道具 举报
本帖最后由 王明明 于 2012-6-29 08:45 编辑

刚看错了... Integer i = 100;
没看到你的是 Integer i = 100;
没问题呀
回复 使用道具 举报
我给你分析为什么不能同步的原因吧..
public class A implements Runnable {
        public static void main(String[] args) {
                A a = new A();
                Thread t1 = new Thread(a);
                Thread t2 = new Thread(a);
                Thread t3 = new Thread(a);
                t1.start();
                t2.start();
                t3.start();
        }

        Integer i = 100;
        //Object o = new Object();
        public void run() {
                while (true)
                {
                        synchronized (i) {//就比如一线程进去了这儿锁的是1,但这个线程挂在try语句里边了,那么另一个二线程就有可能进去,等一线程醒来去执行i--,二线程可能不执行try就直接去i--了,导致出现-1..
                                if (i>0)
                                {
                                        try {
                                                Thread.sleep(20);
                                        } catch (Exception e) {
                                                e.printStackTrace();
                                        }
                                        System.out.println(Thread.currentThread().getName()+" == "+i--);//另外这个语句要放在finally语句里边....要不会出现线程问题..
  1. Thread-0 == 46
  2. Thread-1 == 45
  3. Thread-1 == 44
  4. Thread-0 == 42
  5. Thread-2 == 43
  6. Thread-0 == 41
  7. Thread-0 == 40
  8. Thread-1 == 39
  9. Thread-2 == 38
复制代码
43出现在42后边...
                                }
                        }
                }
        }
}

评分

参与人数 1技术分 +1 收起 理由
刘蕴学 + 1

查看全部评分

回复 使用道具 举报
下面的例子能够说明
  1. class A implements Runnable {
  2.          public static void main(String[] args) {
  3.                  A a = new A();
  4.                  Thread t1 = new Thread(a);
  5.                  Thread t2 = new Thread(a);
  6.                  Thread t3 = new Thread(a);
  7.                  t1.start();
  8.                  t2.start();
  9.                  t3.start();
  10.          }
  11.         Integer i = 100;
  12.         Integer p = 100;
  13.          //Object o = new Object();
  14.          public void run() {
  15.                  while (true)
  16.                  {
  17.                          synchronized (i) {
  18.                                  if (p>0)
  19.                                  {
  20.                                          try {
  21.                                                  Thread.sleep(20);
  22.                                          } catch (Exception e) {
  23.                                                  e.printStackTrace();
  24.                                          }
  25.                                          //System.out.println(Thread.currentThread().getName()+" == "+i--);
  26.                                          System.out.println(Thread.currentThread().getName()+" == "+p--);
  27.                                  }
  28.                          }
  29.                  }
  30.          }
  31. }
复制代码
你只要不执行i--就没事.
或者,你可以在同步判断条件上设一个断点,在eclipse里面会很清晰的看到,由于执行了i--也就是相当于i=i-1的语句之后,变量的引用发生了变化

点评

再说为啥你不用一个终态的本地变量在使结果保持正确?  发表于 2012-6-29 13:40
养成把注释或者解说嵌入到代码里,看起来更直观  发表于 2012-6-29 13:38

评分

参与人数 1技术分 +1 收起 理由
刘蕴学 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马