Search code examples
javamultithreadingsynchronizationsynchronized

Thread synchronizing - almost same expressions but different result


public class MythreadM {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Msg m = new Msg();
        Mythread thread1 = new Mythread(m);
        thread1.start();
        
        Mythread thread2 = new Mythread(m);
        thread2.start();
        
        Mythread thread3 = new Mythread(m);
        thread3.start();
    }

}
class Mythread extends Thread
{
    private Msg m;
    
    Mythread(Msg m)
    {
        this.m = m;
    }
    public void run() 
    {
        System.out.println(getName()+"start");
        for(int i=0; i<300; i++)
        {
            processMsg(i);
        }
    }
    synchronized void processMsg(int i) // here starts question.
    {
//      synchronized(m)
        {
            m.write(getName()+" message "+i);
            try {
                sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            m.print();
        }   
    }
    
}

class Msg
{
    String str = "def message";
    
    void print()
    {
        System.out.println(str+" "+System.currentTimeMillis());
    }
    void write(String str)
    {
        this.str = str;
    }
    
}

Full code above-----------------

and following 3 codes with almost same expressions.

<< code 1 >> : synchronized(m) {}

    void processMsg(int i)
    {
        synchronized(m)
        {
            m.write(getName()+" message "+i);
            try {
                sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            m.print();
        }   
    }

<< code 2 >> : synchronized void processMsg(int i)

    synchronized void processMsg(int i)
    {

        {
            m.write(getName()+" message "+i);
            try {
                sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            m.print();
        }   
    }

It looks these codes mean same just with different expressions but acts different.
< code 2 > is not synchronized, prints non-synchronized results.
Why is this happening?
And what's the purpose of the sleep(1); ? Thanks in advance.


Solution

  • It seems like this is example code to demonstrate that when synchronize on an object common to all threads (m), only one thread at a time can use it, as opposed to when you synchronize a method in the thread, which doesn't do anything because each thread is getting it's own lock.

    To your second question, the meaning of sleep(1) is that the current thread should wait for at least 1 millisecond before proceeding.

    Finally, in my experience, when you have several threads that are after the same resource (especially a (Print)stream like System.out) that the best way to solve this is to have a message queue to ynchronize the messages going out.