开发者

Strange problem with simple multithreading program in Java

I am just starting play with multithreading programming. I would like to my program show alternately character '-' and '+' but it doesn't. My task is to use synchronized keyword. As far I have:

class FunnyStringGenerator{

    private char c;

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

    public synchronized char next(){

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

        return c;
    }
}

c开发者_运维技巧lass 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));
        }

    }

}

EDIT: I also testing Thread.sleep in run method instead for loop.


Your synchronized block in FunnyStringGenerator.next() is working fine. It will return '+' and '-' alternately.

However you have a race condition in ThreadToGenerateStr.run():

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

This is equivalent to:

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

The problem occurs when:

  • Thread 1 calls gen.next(), getting a result of '-'
  • Thread 2 calls gen.next(), getting a result of '+'
  • Thread 2 calls System.out.print(), writing '+'
  • Thread 1 calls System.out.print(), writing '-'

The result is that the '+' and '-' are written in the opposite order.

There are various possible workarounds, e.g.:

  • Call both gen.next() and System.out.print() in a single synchronized block (as in dogbane's answer)
  • Make gen.next() write the character to the stream instead of returning it
  • Make gen.next() append the character to a shared BlockingQueue and have a dedicated I/O thread taking characters from this queue and printing them.


Instead of synchronizing the method, do this:

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

You need to wrap the entire print statement in a synchronized block so that another thread cannot change the value of c before you print it.

Think of it as two statements:

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


Please use two threads for printing each character and use this concept of wait and notify.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜