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

© forTomorrow 中级黑马   /  2015-6-4 19:32  /  1610 人查看  /  33 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

大家看看,为什么我加了同步,有时候程序运行也会出现不同步的情况呢
class RunImp implements Runnable {
    public static int count = 0;

    public  void run() {
        while (count < 5) {
            synchronized (this) {
               
                count++;
                System.out.println(Thread.currentThread().getName() + "--------"
                        + count);
            }
        }
    }
}

public class ThreadTest2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Thread(new RunImp()).start();
        new Thread(new RunImp()).start();
    }

}
尝试很多次,有一次运行结果是这样的:
Thread-0--------2
Thread-0--------3
Thread-0--------4
Thread-0--------5
Thread-1--------2
大多情况都同步的

评分

参与人数 1技术分 +1 收起 理由
lwj123 + 1

查看全部评分

33 个回复

正序浏览
还没学到,先学习学习。。。。
回复 使用道具 举报
hellotaomi 发表于 2015-6-5 14:01
new了两个线程,两个线程对应的对象就不一样吧,那怎么还能用this作为说同步锁的对象呢 ...

嗯 说的对 是两个对象 所以应该是用类名.class作为锁旗标,this表示对象锁
回复 使用道具 举报
pp7803515 发表于 2015-6-5 14:00
new Thread(new RunImp()).start();
        new Thread(new RunImp()).start();
你这里写的是2次,如果我 ...

理解的很正确
回复 使用道具 举报
new了两个线程,两个线程对应的对象就不一样吧,那怎么还能用this作为说同步锁的对象呢
回复 使用道具 举报
new Thread(new RunImp()).start();
        new Thread(new RunImp()).start();
你这里写的是2次,如果我改为
   RunImp ri= new RunImp();
                new Thread(ri).start();
                new Thread(ri).start();
这样的话调用的应该就是同一个对象了,而不是不同对象了吧。不知道我的理解有没有错
回复 使用道具 举报
同步的意思不是说。例如我多个窗口在卖火车票(也就是多线程的时候,调用同一个对象),我A窗口和B窗口出火车票的时候,不能出现同一个座位的火车票吗?
回复 使用道具 举报
探索者 发表于 2015-6-5 11:28
刚才想了一下,你的理解是对的,只是之前在程序了试了唯一字节码对多个对象的情况,发现也有不同步,所以 ...

恩恩,多多探讨,大家才能共同进步,加油
回复 使用道具 举报
                 学习中
回复 使用道具 举报
武汉小菜鸟 发表于 2015-6-5 11:08
什么叫同步,简单的说,就是某个对象,同一时刻,只能被一个线程访问,那就叫同步。(我在网上查的)。“ ...

刚才想了一下,你的理解是对的,只是之前在程序了试了唯一字节码对多个对象的情况,发现也有不同步,所以就理解错了,当你提出你的理解,其实自己也不能解释字节码在内存中是唯一的,为什么不能保证多个对象同步?后来有看了一下程序,发现是程序的有点问题,所以是我的理解错了
回复 使用道具 举报
探索者 发表于 2015-6-5 10:56
唯一的字节码只能保证在同一个对象运行成立,但对于多个对象,即使都使用的是一样的字节码文件,但也同步 ...

什么叫同步,简单的说,就是某个对象,同一时刻,只能被一个线程访问,那就叫同步。(我在网上查的)。“唯一字节码保证一个对象访问”,那就能保证同步了。
可能是你我对于同步的理解有点问题。
回复 使用道具 举报
武汉小菜鸟 发表于 2015-6-5 10:47
如果是唯一的字节码,那么同一时刻只能有一个对象访问同步代码块,就能保证安全问题。你试试 ...

唯一的字节码只能保证在同一个对象运行成立,但对于多个对象,即使都使用的是一样的字节码文件,但也同步不了。不相信可以自己试试,或者在仔细看一下视频
回复 使用道具 举报
forTomorrow 发表于 2015-6-5 08:48
我比较赞同你的观点,我感觉也是this表示的是不同对象,所以导致不是同一把锁,改为类的字节码应该就可以 ...

恩,this代表当前对象,谁调用代表谁,所以不能保证同步的安全问题。可以改为字节码试试
回复 使用道具 举报
探索者 发表于 2015-6-5 10:42
如果建立的是两个对象,那么即使改变锁对象为唯一的字节码文件,也是起不到同步的作用 ...

如果是唯一的字节码,那么同一时刻只能有一个对象访问同步代码块,就能保证安全问题。你试试
回复 使用道具 举报
武汉小菜鸟 发表于 2015-6-4 23:21
你好,你这样也不对!
他这里是this的问题,加同步锁是为了同一时刻只有一个对象在执行代码块,这里传thi ...

如果建立的是两个对象,那么即使改变锁对象为唯一的字节码文件,也是起不到同步的作用
回复 使用道具 举报
forTomorrow 发表于 2015-6-5 08:57
修改后的代码:

package com.itheima;

这个方式是不行的,建立的还是两个对象,虽然你用了唯一的字节码文件作为锁,但对于两个对象,就相对于有两把锁,每一个对象的锁都有唯一的钥匙,但由于不是在同一个对象运行,即使使用的锁为字节码文件,也起不到同步的作用。
回复 使用道具 举报
实现方式二:

package com.itheima;

class RunImp implements Runnable {
        private int count = 0;
        public  void run() {
                while (count < 5) {
                        synchronized (RunImp.class) {       
                                if(count>=5)
                                        break;
                                count++;
                                System.out.println(Thread.currentThread().getName() + "--------"
                                                + count);
                        }
                }
        }
}

public class ThreadTest2 {

        public static void main(String[] args) {
                // TODO Auto-generated method stub
                RunImp runImp = new RunImp();
                new Thread(runImp).start();
                new Thread(runImp).start();
        }

}
回复 使用道具 举报
修改后的代码:

package com.itheima;

class RunImp implements Runnable {
        public static int count = 0;

        public  void run() {
                while (count < 5) {
                        synchronized (RunImp.class) {       
                                if(count>=5)
                                        break;
                                count++;
                                System.out.println(Thread.currentThread().getName() + "--------"
                                                + count);
                        }
                }
        }
}

public class ThreadTest2 {

        public static void main(String[] args) {
                // TODO Auto-generated method stub
                new Thread(new RunImp()).start();
                new Thread(new RunImp()).start();
        }

}
回复 使用道具 举报
武汉小菜鸟 发表于 2015-6-4 23:21
你好,你这样也不对!
他这里是this的问题,加同步锁是为了同一时刻只有一个对象在执行代码块,这里传thi ...

我比较赞同你的观点,我感觉也是this表示的是不同对象,所以导致不是同一把锁,改为类的字节码应该就可以,还没测试
回复 使用道具 举报
半月 发表于 2015-6-4 22:35
对象不是同一个,但是count是静态的,只有一个啊.
他那个只要把synchronized拿到while外面就可以了
但是我 ...

这哥们是正解。你传的this,那个线程调用代表那个对吧,那就代表不同的对象。所以你这个不能保证同步。只需改变同步对象。
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马