你居然操作了sflag,3个线程公用一个sflag,如果同时操作出现flag!=sflag,那你的while不就成了死循环了?

解决方案 »

  1.   

    问题估计在这里: sflag=(sflag+1)%3;
    当时sflag+1==4;其他两个线程正好flag!=sflag,三个线程均死循环
      

  2.   

    楼主,你把那两行锁注释掉就没有这个问题了
    解释:
    以下这段代码不是线程安全的
      Integer i = 0;
      synchronized(i) {
        i++;
      }
    ......
    原因是Java的自动封箱和解箱操作在作怪。
    这里的i++实际上是i = new Integer(i+1),所以执行完i++后,i已经不是原来的对象了,同步块自然就无效了。其它基本类型的封装类,如Short、Long等等也不能作为同步对象。
    so. 最好用专门的锁服务来完成互斥操作
      

  3.   

    这个肯定有可能出现死循环,之所在大家都没有出现死循环,是因为当好时间片段切换到了合适的线程,得以让线程继续下去.上述程序不出现死循环的结果肯定是"a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c ".这个程序,只要减少或者增加一个线程,就会马上出现死循环,楼主只用一个线程DEBUG一下马上就明白.上面之所以不出现死循环,是因为时间片切得刚刚好,第一个线程走完flag=1了,马上切到第二个线程,第二个线程走完flag=2又切到第三个线程,第三个走完flag=0又回到第一个线程.如此类推,每次flag的值刚好是线程输入的值,所以不出现死循环.但执行结果是一样的.倘若线程切得不准,立马就死循环了.
      

  4.   

    我加上同步运行了1644次,也没有死循环。
    10楼说的,“上面之所以不出现死循环,是因为时间片切得刚刚好,第一个线程走完flag=1了,马上切到第二个线程,第二个线程走完flag=2又切到第三个线程,第三个走完flag=0又回到第一个线程”,我觉得不太可能是这样。可以在run()方法里加一句输出:
    System.out.println("current thtread is" + Thread.currentThread().getName());
    就能看出来。
      

  5.   

    纠正一下,我想表达的意思是,假设flag=1了,这个时候,不会出现死循环的只有pt1这个线程,只有当pt1这个线程抢到资源了,程序就会进行下去(当中pt0,pt3互抢了N次)。如果存在一种情况使得flag=1时pt1一直抢不到资源,这个时候就会出现死循环了。
      

  6.   

    应该是同时操作了sflag导致每次判断都flag!=sflag
      

  7.   

    三个线程操作同一个变量sflag 存在抢时间片的问题    如果 flag==sflag 条件不满足 那么count--不会执行  while(count > 0)也就一直会满足 然后死循环
      

  8.   

    确实有出现死循环的情况吗?
    我执行了一下代码,没有碰到死循环的情况啊
    现在倒推一下,出现死循环,就是count 始终大于0,count--无法执行,flag == sflag 一直不成立
    三个线程的 flag 分别为  0、1、2 ,(正常情况下 sflag  的初始值为 0,值集合为{0,1,2}),但是  flag == sflag 一直不成立
    所以 sflag 的值已经不再是{0,1,2},这种情况 怎么才会出现
      

  9.   

    写个简单的正确实现吧,下面是代码,如果需求复杂点,或者需要更灵活的应用,可以再提,我完整看过编程思想的线程部分,jvm的线程部分,系统学习Java 并发编程实战(整本书都理解,并对jdk 1.5的并发框架有研究)
      

  10.   

    package com.tong.therad.wait;class PrintThread extends Thread {
        private final int flag;
        private static Integer sflag = 0;
        private static Object lock = new Object();    public PrintThread(int flag) {
            this.flag = flag;
        }    public void run() {
            int count = 10;
            while (count > 0) {
                synchronized (lock) {
                    if (flag == sflag) {
                        System.out.print((char) ('a' + flag) + " ");
                        count--;
                        sflag = (sflag + 1) % 3;
                        lock.notifyAll();// 唤醒所有
                    } else {
                        try {
                            lock.wait();// 等待被唤醒,释放lock,唤醒时重新获取lock
                        } catch (InterruptedException ignore) {
                        }
                    }
                }
            }
        }
    }public class Wait {    public static void main(String[] args) {
            PrintThread pt0 = new PrintThread(0);
            PrintThread pt1 = new PrintThread(1);
            PrintThread pt2 = new PrintThread(2);
            pt0.start();
            pt1.start();
            pt2.start();
        }}
      

  11.   

    看到main里面的start.,你是否想到Executor框架,看到wait,notifyAll,是否想到await和signalAll,如果你要理解并发,Java 并发编程实战 可以带你走进去,搜索一个AQS,你能学到很多(AbstractQueuedSynchronizer)
      

  12.   

    看了这么多人这么多回答, 没一个对的, 
    private static Integer sflag=0; 改成 private volatile static Integer sflag=0;问题解决
      

  13.   


    呵呵,确实是可见性的问题,while实际上相当于自旋了。
    之前一直不明白为什么死循环,想来想去,不管时间片怎么分,都不会死循环来着。
      

  14.   

    flag!=sflag
    里层不执行,所以 都是count > 10,就死循环吧.