Java中简单多线程程序的奇怪问题

时间:2011-01-16 16:13:46

标签: java multithreading concurrency

我刚刚开始玩多线程编程。我希望我的节目交替显示字符' - '和'+',但事实并非如此。我的任务是使用synchronized关键字。到目前为止我已经:

class FunnyStringGenerator{

    private char c;

    public FunnyStringGenerator(){
        c = '-';
    }

    public synchronized char next(){

        if(c == '-'){
            c = '+';
        }
        else{
            c = '-';
        }

        return c;
    }
}

class ThreadToGenerateStr implements Runnable{

    FunnyStringGenerator gen;

    public ThreadToGenerateStr(FunnyStringGenerator fsg){
        gen = fsg;
    }

    @Override
    public void run() {
        for(int i = 0; i < 10; i++){

            System.out.print(gen.next());
        }
    }


}

public class Main{


    public static void main(String[] args) throws IOException {

        FunnyStringGenerator FSG = new FunnyStringGenerator();

        ExecutorService exec = Executors.newCachedThreadPool();

        for(int i = 0; i < 20; i++){
            exec.execute(new ThreadToGenerateStr(FSG));
        }

    }

}

编辑:我还在运行方法中测试Thread.sleep而不是for循环。

3 个答案:

答案 0 :(得分:5)

synchronized中的FunnyStringGenerator.next()阻止工作正常。它会交替返回'+''-'

但是您在ThreadToGenerateStr.run()中遇到了竞争条件:

System.out.print(gen.next());

这相当于:

char c = gen.next(); // Synchronized
System.out.print(c); // Not synchronized

问题发生在:

  • 线程1调用gen.next(),得到' - '
  • 的结果
  • 线程2调用gen.next(),得到'+'
  • 的结果
  • 线程2调用System.out.print(),写入'+'
  • 线程1调用System.out.print(),写入' - '

结果是'+'和' - '以相反的顺序写出。

有各种可能的解决方法,例如:

  • 在单个synchronized块中调用gen.next()和System.out.print()(如dogbane的回答)
  • 让gen.next()将字符写入流而不是将其返回
  • make gen.next()将该字符附加到共享的BlockingQueue,并有一个专用的I / O线程从该队列中获取字符并打印它们。

答案 1 :(得分:3)

而不是同步方法,请执行以下操作:

        synchronized (gen) {
            System.out.print(gen.next());
        }

您需要将整个print语句包装在synchronized块中,以便其他线程在打印之前无法更改c的值。

将其视为两个陈述:

char n = gen.next();
System.out.print(n);

答案 2 :(得分:-1)

请使用两个线程打印每个字符,并使用等待和通知的概念。