vrnvav97
vrnvav97

Reputation: 53

Thread Synchronization in java

Why I'm not able to achieve Synchronization on this below piece of program:

class P
{

synchronized void pp(String s)
    {
        System.out.println (s);
    }
}

class threadA extends Thread 
{
    P ob;
    String s;
    threadA (P ob, String s)
    {
        this.ob = ob;
        this.s = s;
    }
    public void run ()
    {
        for (int i=1;i<=5;++i)
        {
        ob.pp (s);
        try
        {
            Thread.sleep (1000);
        }
        catch (Exception e) {}
        }
    }
}


class gain 
{
    public static void main(String[] args) {
        P ob = new P ();
        threadA a = new threadA (ob,"Hello User");
        threadA b = new threadA (ob,"Bye User");
        a.start();
        b.start();
    }
}

OP:

Hello User

Bye User

Hello User

Bye User

Bye User

...

I want OP in the form of:

Hello User

Hello User

Hello User..

Bye User

Bye User

Bye User..

or my concept of synchronization is wrong?

Upvotes: 1

Views: 173

Answers (4)

Peter Lawrey
Peter Lawrey

Reputation: 533870

can u explain me the flow of control of my program?

"Hello" starts and run through the loop until it reaches the synchronized method

"Bye" does the same.

"Hello" is the first to acquire the lock.

"Bye" blocks waiting for the lock.

"Hello" executes the method and releases the lock.

"Bye" can now acquire the lock and "Hello" has released it

"Bye" can now execute the method, and releases the lock as "Hello" did.

what can I do so that hello after executing the method goes to blocked pool and also doesn't leaves the lock for bye to acquire it

Hold the lock, and don't release it if you want to retain it.

public void run() {
    synchronized(ob); { // hold the lock the whole time
        for (int i = 1; i <= 5; ++i) {
            ob.pp (s);
            try { Thread.sleep(1000); } catch (Exception e) {}
        }
    } // releases the lock here.
}

Upvotes: 1

Jai
Jai

Reputation: 8363

You cannot do such synchronization from P class. What happens now is that any calls to pp() is blocked if another thread is currently executing the method. As long as the method ends (which is quick if you are just going to print things to the console), the next thread would be allowed to enter the method.

What you are trying to achieve is not possible, unless both the threads are aware of each other and communicate with each other. In other words, when the first thread finishes what it needs to do, it should explicitly inform the second thread to start. This is effectively executing sequentially, instead of parallelly.

Update

You wanted to visualize what is happening so I'll do it here.

  1. You created 2 threads.
  2. You start the first thread.
  3. The first thread starts to run, while some time later the second starts to run as well.
  4. When your first thread runs, it goes to the for loop. Then it calls P.pp().
  5. When P.pp() is called from first thread, it locks the P object.
  6. Since the method is so short, it is going to exit very quickly.
  7. When the method exits, it releases the lock on P.
  8. If your second thread reaches the synchronize block before the first thread exits, it will wait (blocked).
  9. When the first thread exits, the second thread enters as the first thread releases the lock.
  10. The first thread returns to the loop and try to call P.pp() again.
  11. This will continue, depending on which thread is faster, the order of execution would be different.

Upvotes: 2

Vinayak Shanbhag
Vinayak Shanbhag

Reputation: 902

You should try something like this

class P
{

void pp(String s)
    {
        System.out.println (s);
    }
}

class threadA extends Thread 
{
    P ob;
    String s;
    threadA (P ob, String s)
    {
        this.ob = ob;
        this.s = s;
    }
    public void run ()
    {
        for (int i=1;i<=5;++i)
        {
            synchronized(ob)
            {
               ob.pp (s);
                try
                {
                    Thread.sleep (10);
                }
                catch (Exception e) {}
            }


        }
    }
}


public class gain 
{
    public static void main(String[] args) {
        P ob = new P ();
        threadA a = new threadA (ob,"Hello User");
        threadA b = new threadA (ob,"Bye User");
        a.start();
        b.start();
    }
}

i.e while sleeping keep thread synchronized so that you get required output or else you are not sure which thread might come up first after sleep. See this

Upvotes: 1

robob
robob

Reputation: 1759

Synchronized keyword means that two threads on that code block have to respect the order they tried to access that block code. It doesn't mean that the execution flow is serialized.

To have what you want try to put the for inside the synchronized block...

Upvotes: 1

Related Questions