synchronisation problem

T

tom fredriksen

Hi

I was doing test to understand threading better (haven't done much of
thread programming at all, been a process guy instead). And I was trying
to create an object and have two threads work on it at the same time,
and I noticed something I don't quite understand.

I have a synchronised method, which update an instance variable. To test
that it does lock the object and serialises the access to the method, I
put in a sleep() in the method. The problem is that if I do that it
seems to affect the order of the execution of the threads. The method is
the following (full code at the end)

public synchronized int add1() throws InterruptedException
{
System.out.println(Thread.currentThread().getName() + ": add1 = " +
test1);
test1++;
// Thread.sleep(sleep1);

return(0);
}

Here are the results while running the test, "T2" is the name of the
second thread, this is reproducible. Even if it locks the object, as
soon as it leaves the method, the lock is removed and the other thread,
which is waiting, should enter. If I put the sleep() in the run method
it works as expected, but that produces uninteresting results. The
reason is that it then does not show what happens with the other thread
when the object is locked, but rather what happens outside a
synchronised method, which is what one expects; two threads not running
at the same time.

Can anybody explain to me why this is?


With sleep in add1():

Thread-0: add1 = 1000
Thread-0: add1 = 1001
Thread-0: add1 = 1002
Thread-0: add1 = 1003
Thread-0: add1 = 1004
Thread-0: add1 = 1005
Thread-0: add1 = 1006
Thread-0: add1 = 1007
Thread-0: add1 = 1008
Thread-0: add1 = 1009
T2: add1 = 1010
T2: add1 = 1011
T2: add1 = 1012
T2: add1 = 1013
T2: add1 = 1014
T2: add1 = 1015
T2: add1 = 1016
T2: add1 = 1017
T2: add1 = 1018
T2: add1 = 1019


Without sleep in add1(), but with sleep in run():

Thread-0: add1 = 1000
T2: add1 = 1001
Thread-0: add1 = 1002
T2: add1 = 1003
Thread-0: add1 = 1004
T2: add1 = 1005
Thread-0: add1 = 1006
T2: add1 = 1007
Thread-0: add1 = 1008
T2: add1 = 1009
Thread-0: add1 = 1010
T2: add1 = 1011
Thread-0: add1 = 1012
T2: add1 = 1013
Thread-0: add1 = 1014
T2: add1 = 1015
Thread-0: add1 = 1016
T2: add1 = 1017
Thread-0: add1 = 1018
T2: add1 = 1019




import java.util.*;

public class SyncTest extends Thread
{
private int test1;
private int sleep1;

public SyncTest(int start, int sleep)
{
test1 = start;
sleep1 = sleep;
}

public synchronized int add1() throws InterruptedException
{
System.out.println(Thread.currentThread().getName() + ": add1 = " +
test1);
test1++;
// Thread.sleep(sleep1);

return(0);
}

public void run()
{
try {
for(int c=0; c<10; c++) {
add1();
Thread.sleep(sleep1);
}
} catch (InterruptedException e) {
System.out.println(e);
return;
}
}

public static void main(String args[]) throws InterruptedException
{
SyncTest b = new SyncTest(1000, 1000);

b.start();
new Thread(b, "T2").start();

return;
}
}
 
P

Patricia Shanahan

tom said:
Here are the results while running the test, "T2" is the name of the
second thread, this is reproducible. Even if it locks the object, as
soon as it leaves the method, the lock is removed and the other thread,
which is waiting, should enter.

Why do you consider this to be required behavior? Remember it would
require the CPU dispatcher to switch which thread is running while the
current thread is runnable and has not accumulated much CPU time.

There are often many ways the instructions in different threads can be
interleaved while conforming to all relevant standards. This is the
thing that makes designing, writing, and testing multithreaded programs
such fun. As far as I know, both the execution orders you show, and
numerous other interleavings of the add methods in the two threads, are
perfectly legal.

With the sleep in run, not add1, I get the threads interleaved on a
Windows XP laptop, but the same behavior as you get when I run the same
class file on a Linux system.

Patricia
 
T

tom fredriksen

Patricia said:
Why do you consider this to be required behavior? Remember it would
require the CPU dispatcher to switch which thread is running while the
current thread is runnable and has not accumulated much CPU time.

I was thinking that a sleep could be representative of some work, but of
course its not. I rewrote the example, removed the sleep() and added
some loop work of various time length instead. Now I at least see some
interleaved work being performed. Thanks.

/tom
 
O

Oliver Wong

Patricia Shanahan said:
There are often many ways the instructions in different threads can be
interleaved while conforming to all relevant standards. This is the
thing that makes designing, writing, and testing multithreaded programs
such fun.

I like how you use "fun" as a euphamism for "mind-numbingly
aggravating".

- Oliver
 
C

Carl Burke

....
public synchronized int add1() throws InterruptedException
{
System.out.println(Thread.currentThread().getName() + ": add1 = " +
test1);
test1++;
// Thread.sleep(sleep1);

return(0);
}

Here are the results while running the test, "T2" is the name of the
second thread, this is reproducible. Even if it locks the object, as soon
as it leaves the method, the lock is removed and the other thread, which
is waiting, should enter. If I put the sleep() in the run method it works
as expected, but that produces uninteresting results. The reason is that
it then does not show what happens with the other thread when the object
is locked, but rather what happens outside a synchronised method, which is
what one expects; two threads not running at the same time.

Can anybody explain to me why this is?

With the sleep inside add1, you sleep without releasing the lock.
The synchronized add1() calls in other threads can't be activated
while your first thread is sleeping because the object is unavailable.
The method doesn't return until after the sleep is completed.
So the first thread comes back from sleep and forges on ahead,
releasing the lock but not yielding control. Since that thread never
yields control while 'b' is unlocked, none of the other threads gets
a chance to act.

As other posters have noted, even when you code it correctly you aren't
guaranteed to get the results you expected, but you are guaranteed to NOT
get the results you expected when you sleep inside a synchronized method.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top