Why does adding a synchronized block around this code change program ouput? - java

class Demo extends Thread{
Test x;
String name;
String task;
public Demo(String name, String task, Test p){
this.name = name;
this.task = task;
x = p;
}
public void run(){
synchronized (x) {
x.message(name, task);
}
}
public static void main(String[] args) {
Test t = new Test();
Demo d = new Demo("Jack", "Cutting",t);
Demo d1 = new Demo("Jacoe", "Cooking",t);
Demo d2 = new Demo("Bob", "Cleaning",t);
d.start();
d1.start();
d2.start();
}
}
class Test{
void message(String name, String task){
System.out.println(name);
try{
Thread.sleep(5000);
}catch(Exception e){
}
System.out.println(task);
}
}
This is a simple program I created to practice multithreading and synchronization in java. I was wondering if somebody can explain to me why the output is different when the synchronized block is removed from the public void run() method?
With:
With synchronized block
Without:
Without synchronized block

The program starts threads. The OS has to schedule when they run, which can seem arbitrary. Then without locking the threads may interleave their actions.
In the synchronized case, all the threads' run methods are synchronizing on the same object, so only one of them can execute at a time. There is no guarantee which of them comes first, the scheduler can pick whichever it wants. In your case it picked the third thread before the second one.
The individual output lines don't get interleaved in any case because the printstream is synchronized.

The output was never deterministically ordered or guaranteed to be the same order. It was always "undefined; the system can do it in whatever order it ends up doing."

synchronized is like the lock statement in c#
Only one thread can enter the synchronized block at the same time.
The other threads have to wait in front of the synchronized block.
Total runtime with synchronized should be 15 sec.
Total runtime without should be 5 sec, because all 3 Threads run at the same time.

Related

Why thread still locks after synchronised method is executed?

I'm reading java multithreading tutorial which says thread only gives up key until it completes synchronised method, however when I run the following code (about 20 times):
public class SyncDemo implements Runnable{
#Override
public void run() {
for (int i = 0; i < 10; i++) {
sync();
}
}
private synchronized void sync() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
SyncDemo s = new SyncDemo();
Thread a = new Thread(s, "a");
Thread b = new Thread(s, "b");
a.start();
b.start();
}
}
it only prints a then b, which I expect a mixed sequence of them because current thread will unlock every time after sync() is executed inside the loop? Thus giving the other thread a chance to print its name?
There is nothing in your program that would demand a certain execution order. So the run time will schedule the threads in a way that makes most sense in the current situation. Factors that may influence the order are number of processors, load situation, ...

Multiple Threads accessing instance method from different Instances should cause a race condition?

I am trying to understand Synchornized in Java.
I understood if I have access a synchronized method on same object from 2 different Threads, only one will be able to access at a time.
But I think if the same method is being called on 2 different instances, Both Objects should be able to access the method parallel. Which would cause race condition if accessing/modifying a static member variable from the method. But I am not able to see the race condition happening in below code.
Could someone please explain whats wrong with the code or my understanding.
For reference code is accessible at : http://ideone.com/wo6h4R
class MyClass
{
public static int count=0;
public int getCount()
{
System.out.println("Inside getcount()");
return count;
}
public synchronized void incrementCount()
{
count=count+1;
}
}
class Ideone
{
public static void main(String[] args) throws InterruptedException {
final MyClass test1 = new MyClass();
final MyClass test2 = new MyClass();
Thread t1 = new Thread() {
public void run()
{
int k=0;
while (k++<50000000)
{
test1.incrementCount();
}
}
};
Thread t2 = new Thread() {
public void run()
{
int l=0;
while (l++<50000000)
{
test2.incrementCount();
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
//System.out.println(t2.getState());
int x=500000000+500000000;
System.out.println(x);
System.out.println("count = " + MyClass.count);
}
}
You're right that the race condition exists. But the racy operations are so quick that they're unlikely to happen -- and the synchronized keywords are likely providing synchronization "help" that, while not required by the JLS, hide the races.
If you want to make it a bit more obvious, you can "spell out" the count = count + 1 code and put in a sleep:
public synchronized void incrementCount()
{
int tmp = count + 1;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count=tmp;
}
That should show the races more easily. (My handling of the interrupted exception is not good for production code, btw; but it's good enough for small test apps like this.)
The lesson learned here is: race conditions can be really hard to catch through testing, so it's best to really understand the code and prove to yourself that it's right.
Since syncrhonized methods actually synchronize on this different instance methods will lock on different objects and therefore you will get race conditions since they don't block each other.
You probably have to make your own lock object and lock on that.
class MyClass
{
public static int count=0;
//this is what you lock on
private static Object lock = new Object();
public int getCount()
{
synchronized(lock){
System.out.println("Inside getcount()");
return count;
}
}
public void incrementCount()
{
synchronized(lock){
count = count+1;
}
}
//etc
Now when you run your main, this gets printed out:
1000000000
count = 100000000
Here's the relevant section of the Java specification:
"A synchronized method acquires a monitor (ยง17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used."
However I fail to see where the MyClass' instances are actually incrementing "count" so what exactly are you expecting to show as a race condition?
(Taken originally from this answer)

How could the two threads enter the synchronized block at the same time?

There is some weird thing happening. As I enter the synchronized block,I try to print the name of the Thread.After the print statement,I make a husge pause of 100000 seconds.
#Override
public int getNextAvailableVm() {
synchronized(this) {
System.out.println(Thread.currentThread().getName());
try {Thread.sleep(100000000);}catch(Exception exc){}
String dataCenter = dcc.getDataCenterName();
int totalVMs = Temp_Algo_Static_Var.vmCountMap.get(dataCenter);
AlgoHelper ah = (AlgoHelper)Temp_Algo_Static_Var.map.get(dataCenter);
.
.
.
}
}
But as this method is run,name oft the 2 threads are printed.
Thread-11
Thread-13
and it is after this that the long pause occurs. Why is that ? How could the two threads enter the synchronized block,when the first thread has yet not left the block ?
If the two threads are running against the same object then this should not happen.
I would therefore suggest that you are creating a new object for each thread or at least some of the threads are running on different objects.
If you do want multiple objects then you should not use synchronized(this), you should create a static final Object to synchronize on. Please do not sync on this.getClass() as that breaks.
Most likely you are invoking getNextAvailableVm() on different instances of the containing class. Since you are synchronizing on this you will be locking on two different monitors (first thread locks on instance1, second one on instance2).
There are a lot of ways you could correct this:
make the whole method synchronized
synchronize on this.getClass()
define a static object to lock on
use methods from java.util.concurrent.locks to do the locking
These are just some suggestions to address your problem, but to find the right one we would have to know more about your application structure and your requirements.
I guess the below prog, will work like you expected,
Locked on Thread1.Class, Two thread will not execute the method simultaneously
public class Test {
public static void main(String [] args) {
Thread1 t1 = new Thread1();
Thread1 t2 = new Thread1();
t1.start();
t2.start();
}
}
class Thread1 extends Thread{
public void run(){
getNextAvailableVm();
}
public void getNextAvailableVm() {
synchronized(Thread1.class) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
}catch(Exception exc){}
System.out.println(Thread.currentThread().getName());
}
}
}
OUTPUT
Thread-1
Thread-1
Thread-0
Thread-0

why is this thread safe?

Because it always prints out '3'. No synchronization needed? I am testing this simple thing because I am having a trouble in a real multiple thread problem, which isn't good to illustrate the problem, because it's large. This is a simplified version to showcase the situation.
class Test {
public static int count = 0;
class CountThread extends Thread {
public void run()
{
count++;
}
}
public void add(){
CountThread a = new CountThread();
CountThread b = new CountThread();
CountThread c = new CountThread();
a.start();
b.start();
c.start();
try {
a.join();
b.join();
c.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
Test test = new Test();
System.out.println("START = " + Test.count);
test.add();
System.out.println("END: Account balance = " + Test.count);
}
Because it always prints out '3'. No synchronization needed?
It is not thread safe and you are just getting lucky. If you run this 1000 times, or on different architectures, you will see different output -- i.e. not 3.
I would suggest using AtomicInteger instead of a static field ++ which is not synchronized.
public static AtomicInteger count = new AtomicInteger();
...
public void run() {
count.incrementAndGet();
}
...
Seems to me like count++ is fast enough to finish until you invoke 'run' for the other class. So basically it runs sequential.
But, if this was a real life example, and two different threads were usingCountThread parallelly, then yes, you would have synchronization problem.
To verify that, you can try to print some test output before count++ and after, then you'll see if b.start() is invoking count++ before a.start() finished. Same for c.start().
Consider using AtomicInteger instead, which is way better than synchronizing when possible -
incrementAndGet
public final int incrementAndGet()
Atomically increments by one the current value.
This code is not thread-safe:
public static int count = 0;
class CountThread extends Thread {
public void run()
{
count++;
}
}
You can run this code a million times on one system and it might pass every time. This does not mean is it is thread-safe.
Consider a system where the value in count is copied to multiple processor caches. They all might be updated independently before something forces one of the caches to be copied back to main RAM. Consider that ++ is not an atomic operation. The order of reading and writing of count may cause data to be lost.
The correct way to implement this code (using Java 5 and above):
public static java.util.concurrent.atomic.AtomicInteger count =
new java.util.concurrent.atomic.AtomicInteger();
class CountThread extends Thread {
public void run()
{
count.incrementAndGet();
}
}
It's not thread safe just because the output is right. Creating a thread causes a lot of overhead on the OS side of things, and after that it's just to be expected that that single line of code will be done within a single timeslice. It's not thread safe by any means, just not enough potential conflicts to actually trigger one.
It is not thread safe.
It just happened to be way to short to have measurable chance to show the issue. Consider counting to much higher number (1000000?) in run to increase chance of 2 operations on multiple threads to overlap.
Also make sure your machine is not single core CPU...
To make the class threadsafe either make count volatile to force memory fences between threads, or use AtomicInteger, or rewrite like this (my preference):
class CountThread extends Thread {
private static final Object lock = new Object();
public void run()
{
synchronized(lock) {
count++;
}
}
}

Java synchronized keyword issue

I am trying to understand the keyword synchronized from the following example
Java Main Method -->
public int methodA(){
Hello h = new Hello();
h.callSomeSynchronizedMethod();
sysout("Main");
return 0;
}
In the Hello Class-->
public synchronized void callSomeSynchronizedMethod(){
Hi h = new Hi();
h.someMethod();
sysout("Hello");
}
In the Hi class
public void someMethod(){
sysout("Hi");
}
So what would be the list of outputs that i will get;
1.) Is it in the order of Hi, Hello and Main ?
2.) What i understand about the synchronized keyword is that it will only execute 1 method and then execute the other, without multi-threading. Is this correct ?
To really understand what synchronized does you need to run the program twice, once synchronized and once not. Also your program should use multiple threads. So here is an example of such a test.
public class Synchro {
public static void main(String args[]){
new Synchro();
}
public Synchro(){
final Moo moo = new Moo();
Thread t = new Thread(new Runnable(){
public void run(){
moo.aMethod("Second");
}
});
t.start();//calling the method in a thread
moo.aMethod("First");//calling the same method from the same object in the main thread
}
class Moo{
public Moo(){
}
public void aMethod(String name){
//this loop just prints slowly so you can see the execution
for(int i = 1; i <= 100; i++){
System.out.println(String.format("%s : %d", name, i));
try{
Thread.sleep(50);
}catch(InterruptedException e){}
}
}
}
}
Now, if you run the above code, noticing that the method is not synchronized, you will see the printout from the two executions of the method interleaved. That is you will see First 1 then Second 1 then First 2 etc.
Now, add the synchronized keyword to the method making it:
public synchronized void aMethod(String name){ ....
and run the code again. This time, one execution of the method completes before the other begins.
The synchronized keyword is only necessary when multiple threads are accessing the very same object.
You would get "Hi", then "Hello", then "Main", yes. The synchronized modifier has nothing to do with the order the methods are called in; and, other than adding a bit of overhead, it does nothing at all when running the code in a single thread. You could run this same test without synchronized and get the same result.
Now, if you ran a similar test where multiple threads were calling these methods, your results would be less determinate.
Synchronized is meant to allow for the more safe execution of code and management of resources in a multi-threaded environment.
http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Hope this helps.
all these methods will be executed in one thread so the answer for the first question is "yes".
synchronized keyword emans that the method can be executed in only one thread at every moment of time. So if you call it from another thread - it will wait till the execution is finished in the first thread.
In Java there is no automatic multithreading: you must explicitly start a thread and pass it a run method that it will execute. Only in that case will the synchronized keyword start to matter, but its meaning is not quite as you understand it: the methods will execute in whatever thread calls them, but while one is executing, another thread will block before it is able to execute a method guarded by the same lock.

Categories

Resources