Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Thread Shared Object Synchronization Issue

I'm having issues with Synchronized not behaving the way i expect, i tried using volatile keyword also:

Shared Object:


public class ThreadValue {
private String caller;
private String value;
public ThreadValue( String caller, String value ) {
    this.value = value;
    this.caller = caller;
}

public synchronized String getValue() {
    return this.caller + "     "  + this.value;
}
public synchronized void setValue( String caller, String value ) {
    this.caller = caller;
    this.value = value;
}
}

Thread 1:


class CongoThread implements Runnable {
    private ThreadValue v;
    public CongoThread(ThreadValue v) {
    this.v = v;

    }
    public void run() {
    for (int i = 0; i  10; i++) {
    v.setValue( "congo", "cool" );
    v.getValue();
    }
    }
}

Thread 2:


class LibyaThread implements Runnable {
    private ThreadValue v;
    public LibyaThread(ThreadValue v) {
    this.v = v;

    }
    public void run() {
    for (int i = 0; i  10; i++) {
       v.setValue( "libya", "awesome" );
       System.out.println("In Libya Thread " + v.getValue() );

    }
    }
}

Calling Class:


class TwoThreadsTest {
    public static void main (String args[]) {

    ThreadValue v = new ThreadValue("", "");
        Thread congo = new Thread( new CongoThread( v ) );
        Thread libya = new Thread( new LibyaThread( v ) );

    libya.start();
        congo.start();

    }
}

Occasionally i get "In Libya Thread congo cool" which should never happen. I expect only: "In Libya Thread libya awesome" "In Congo Thread congo cool"

I dont expect them to be mixed.

like image 703
Mo . Avatar asked Jul 31 '26 20:07

Mo .


1 Answers

Why would they not be mixed? Although each individual call is synchronized, there's nothing to stop one thread from calling v.setValue, then the other thread calling setValue, then the first thread calling getValue(). I believe that's what's happening. You could avoid this by using:

public void run() {
    for (int i = 0; i  10; i++) {
       synchronized (v) {
           v.setValue( "libya", "awesome" );
           System.out.println("In Libya Thread " + v.getValue() );
       }
    }
}

That way, on each iteration it makes sure that it calls setValue and getValue without another thread calling setValue in the meantime.

It's not an ideal design, admittedly - but I'm guessing this demonstration is more to understand synchronization than anything else :)

like image 97
Jon Skeet Avatar answered Aug 03 '26 12:08

Jon Skeet