3

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;
    }
}

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));
        }

    }

}

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

3 Answers 3

5

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.
Sign up to request clarification or add additional context in comments.

Comments

3

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);

Comments

-1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.