File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Threads and Synchronization and the fly likes Why this synchronization doesn't work Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Why this synchronization doesn Watch "Why this synchronization doesn New topic
Author

Why this synchronization doesn't work

ShihChao Lin
Greenhorn

Joined: Mar 30, 2003
Posts: 2
Hi:
Can anyone tell me why the synchronized for following code does not work?
public class SyncTest extends Thread{
StringBuffer letter = new StringBuffer("A");
private synchronized void printChar() {
char c;
c = letter.charAt(0);
for (int i=0; i< 5; i++) {
System.out.print(c);
}
System.out.println();
c++;
letter.setCharAt(0, c);
}
public void run(){
printChar();
}
public static void main(String[] args) {
SyncTest t1 = new SyncTest();
SyncTest t2 = new SyncTest();
t1.start();
t2.start();
}
}
I was hoping the output will be
AAAAA
BBBBB
But the result was
AAAAAAAAAA
Thanks for your help
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hi Lin,
Welcome to JavaRanch. The problem here is that you have two different instances of the StringBuffer, both being initialized with "A". If you declare the StringBuffer static, then it will do what you expect.
Michael Morris


Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius - and a lot of courage - to move in the opposite direction. - Ernst F. Schumacher
John Smith
Ranch Hand

Joined: Oct 08, 2001
Posts: 2937
The two threads that you created are absolutely independent and do not share any data. You might as well remove the synchronized qualifier and the result will be identical. To see the results of synchronization, you should create one object, pass it to two or more threads, and invoke the methods of that object from these threads.
Eugene.
John Smith
Ranch Hand

Joined: Oct 08, 2001
Posts: 2937
Michael, you beat me again? By a few seconds?
Eugene.
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Eugene's explaination is clearer than mine and more to the point of your question. Either way, the point of synchronization is to protect a single object from concurrent access and a race condition.
Michael Morris
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Yea, talk about threads in a race condition. But as I noted, yours was the better post.
Michael Morris
ShihChao Lin
Greenhorn

Joined: Mar 30, 2003
Posts: 2
Thanks. I think I got your point.
Andrew Trumper
Greenhorn

Joined: Sep 08, 2001
Posts: 12
Originally posted by ShihChao Lin:
Hi:
Can anyone tell me why the synchronized for following code does not work?
I was hoping the output will be
AAAAA
BBBBB
But the result was
AAAAAAAAAA
Thanks for your help


What you ment to do was:

public class SyncTest extends Thread{
static StringBuffer letter = new StringBuffer("A");
private static synchronized void printChar() {
char c;
c = letter.charAt(0);
for (int i=0; i< 5; i++) {
System.out.print(c);
}
System.out.println("");
c++;
letter.setCharAt(0, c);
}
public void run(){
printChar();
}
public static void main(String[] args) {
SyncTest t1 = new SyncTest();
SyncTest t2 = new SyncTest();
t1.start();
t2.start();
}
}
huang zhiguo
Greenhorn

Joined: Apr 22, 2003
Posts: 1
Is the following codes better?

public class SyncTest implements Runnable{
StringBuffer letter = new StringBuffer("A");
private synchronized void printChar() {
char c;
c = letter.charAt(0);
for (int i=0; i< 5; i++) {
System.out.print(c);
}
System.out.println();
c++;
letter.setCharAt(0, c);
}
public void run(){
printChar();
}
public static void main(String[] args) {
SyncTest thread=new SyncTest();
Thread t1 = new Thread(thread);
Thread t2 = new Thread(thread);
t1.start();
t2.start();
}
}
chi Lin
Ranch Hand

Joined: Aug 24, 2001
Posts: 348
I agree with Huang's point, then I try some experiments with the code, I found something quite confusing here.
In the following code, SyncTest still extends Thread, however, in main() I use Huang's style to generate two threads.
the code compiles & generates expected result.
AAAAA
BBBBB
What I don't get, why those two lines compiles ?
Thread does not have such constructor that take a thread object or its subclass as argument.
Thread t1 = new Thread(thread);
Thread t2 = new Thread(thread);



not so smart guy still curious to learn new stuff every now and then
John Smith
Ranch Hand

Joined: Oct 08, 2001
Posts: 2937
What I don't get, why those two lines compiles ? Thread does not have such constructor that take a thread object or its subclass as argument.
The Thread class has the following constructor: Thread(Runnable target).
Since every instance of Thread implements Runnable, it can be used as an argument for that constructor.
Eugene.
[ April 25, 2003: Message edited by: Eugene Kononov ]
chi Lin
Ranch Hand

Joined: Aug 24, 2001
Posts: 348
Thanks for the clarification.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
What would also have worked is using a shared object as synchronization monitor, for example the class instance:


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
suvasis mukherjee
Greenhorn

Joined: Feb 22, 2003
Posts: 5
hi
huang zhiguo solution is better because of the following reasons:
1. When you subclass Thread as in your case, the Thread object is just ab object that happens to point to the actual thread(a kernel, structure etc). Once a thread exits("stopped"), it's gone. It can not be restarted. Moreover, your intention is not to change nature of thread, so don't subclass it.
2. Whereas a Runnable may be used with as many threads as you like. this is a better solution.
Also, instead of sych the whole thread, you can sych only the loop portion i.e

Object o = new Object();
synchronized(o) {
for (int i=0; i< 5; i++) {
System.out.print(c);
}
}
suvasis

Originally posted by ShihChao Lin:
Hi:
Can anyone tell me why the synchronized for following code does not work?
public class SyncTest extends Thread{
StringBuffer letter = new StringBuffer("A");
private synchronized void printChar() {
char c;
c = letter.charAt(0);
for (int i=0; i< 5; i++) {
System.out.print(c);
}
System.out.println();
c++;
letter.setCharAt(0, c);
}
public void run(){
printChar();
}
public static void main(String[] args) {
SyncTest t1 = new SyncTest();
SyncTest t2 = new SyncTest();
t1.start();
t2.start();
}
}
I was hoping the output will be
AAAAA
BBBBB
But the result was
AAAAAAAAAA
Thanks for your help
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Why this synchronization doesn't work