If an object has a synchronized method A and a not synchronized method B, can both method be called by different threads?
And the answer is:
Only one thread can access synchronized method A at a time (unless there are two different objects and each thread calls method A on different objects). B can be accesed by many threads at any given time, even when A is executing.
At the beginning I was a bit confused about the second part, if that is so, then a class might not be protected against multithreading update if it has at least one non-synchronized method that modifies an instance variable used by a synchronized method. I was right!
Here's is the code to prove it:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This simple class show how synchronized method can be ignored if | |
* there are methods not synchronized that modify the same class instances. | |
* @author Christian Vielma | |
*/ | |
public class SyncVsNotSync { | |
static class MyClass { | |
int value = 0; | |
public synchronized void updateValueA() { | |
value = 1; | |
System.out.println("UpdateValueA - Value is: "+this.value); | |
} | |
public void updateValueB(){ | |
value=0; | |
System.out.println("UpdateValueB - Value is: "+this.value); | |
} | |
} | |
public static void main(String[] args){ | |
final MyClass myclass = new MyClass(); | |
final Random generate = new Random(); | |
Runnable thread1 = new Runnable(){ | |
@Override | |
public void run() { | |
try{ | |
myclass.updateValueA(); | |
Thread.sleep(generate.nextInt(1000)); | |
myclass.updateValueA();} | |
catch (Exception e){ | |
System.out.println(e); | |
} | |
} | |
}; | |
Runnable thread2 = new Runnable(){ | |
@Override | |
public void run() { | |
try{ | |
myclass.updateValueB(); | |
Thread.sleep(generate.nextInt(1000)); | |
myclass.updateValueB(); | |
} | |
catch (Exception e){ | |
System.out.println(e); | |
} | |
} | |
}; | |
Thread t1 = new Thread(thread1); | |
Thread t2 = new Thread(thread2); | |
t1.start(); | |
t2.start(); | |
try{ | |
t1.join(); | |
t2.join(); | |
} catch(Exception e){} | |
finally { | |
System.out.println("Final value: "+myclass.value); | |
} | |
} | |
} |
If you run this code it will sometimes show final value as 0 and other times value as 1. So when designing a class that should be synchronized take under consideration which methods are you leaving free that can modify instance (or static) attributes.
0 comments:
Post a Comment