synchronize seems not work

L

lonelyplanet999

Hi,

I have 2 java programs doing similar things:
==============================================================================
Program 1 below successfully achieved synchronization among 3 created
threads such that the first printed 100 'A' before the second printed
100 'B' followed by the third printed 100 'C'
==============================================================================
class InSync extends Thread {

StringBuffer letter;

public InSync(StringBuffer letter) {
this.letter = letter;
}

public void run() {
synchronized(letter) {
for (int i=1; i<=100; i++) {
System.out.print(letter);
}
System.out.println();
char temp = letter.charAt(0);
++temp;
letter.setCharAt(0,temp);
}
}

public static void main (String [] args) {
StringBuffer sb = new StringBuffer("A");
new InSync(sb).start();
new InSync(sb).start();
new InSync(sb).start();
}

}

==============================================================================
Program 2 below aims to achieve the same function. However, the output
was not expected.

This program outputted below when ran.

Thread-1
AAAAAAAAAThread-3
AAAThread-2
AAAAAAAAAAA...... (80 'A's in one row)
AAAAAAAAAAA...... (80 'A's in one row)
AAAAAAAAAAA...... (80 'A's in one row)
AAAAAA..... (38 'A's in one row)
AACheck c=A
AAAA.... (17 'A's in one row)
ACheck c=A

Check c=A

Obviously, the code couldn't synchronize execution of the three
threads. I couldn't understand what's the difference between program 1
& 2 that caused failure of program 2 to outputted what's outputted by
program 1 ?

Tks ;\
==============================================================================
class Ch9ex2 extends Thread {

private StringBuffer sb = new StringBuffer("A");

public static void main (String [] args) {
Ch9ex2 mt1 = new Ch9ex2();
Ch9ex2 mt2 = new Ch9ex2();
Ch9ex2 mt3 = new Ch9ex2();
mt1.start();
mt2.start();
mt3.start();
}

public void run() {
System.out.println(Thread.currentThread().getName());
synchronized(sb) {
for (int i=0; i<100; i++) {
System.out.print(sb);
}
System.out.println("");
char c = sb.charAt(0);
System.out.println("Check c="+c);
c += 1;
sb.setCharAt(0,c);
}
}

}
 
M

Michael Borgwardt

lonelyplanet999 said:
Obviously, the code couldn't synchronize execution of the three
threads. I couldn't understand what's the difference between program 1
& 2 that caused failure of program 2 to outputted what's outputted by
program 1 ?

Java synchronization works with "monitors". Only one thread at a time can
"own" a particular monitor and execute code that synchronizes on that monitor.
Now the important thing is that each *Object* has its own monitor.

In Program 1, all threads are given (in the constructor) an object to
synchronize on, and it works because in the main method they are given
the same object. In Program 2, each thread has a separate object that
it synchronizes on, and thus effective no synchronization happens.
 
G

Gordon Beaton

Obviously, the code couldn't synchronize execution of the three
threads. I couldn't understand what's the difference between program 1
& 2 that caused failure of program 2 to outputted what's outputted by
program 1 ?

Synchronization is based on obtaining a monitor that is part of the
object you synchronize on. It is through the monitor that the threads
communicate their intention to execute the critical section of code,
and indicate when the code is busy.

Your threads must synchronize on the *same* object, or they will not
be synchronized with each other. It is possible to use different
synchronization objects independently of one another.

In your second example, you create a unique synchronization object in
each thread:
private StringBuffer sb = new StringBuffer("A");

....preventing them from synchronizing with each other.

/gordon
 
L

lonelyplanet999

Michael Borgwardt said:
Java synchronization works with "monitors". Only one thread at a time can
"own" a particular monitor and execute code that synchronizes on that monitor.
Now the important thing is that each *Object* has its own monitor.

In Program 1, all threads are given (in the constructor) an object to
synchronize on, and it works because in the main method they are given
the same object. In Program 2, each thread has a separate object that
it synchronizes on, and thus effective no synchronization happens.

Tks :)
 
L

lonelyplanet999

Gordon Beaton said:
Synchronization is based on obtaining a monitor that is part of the
object you synchronize on. It is through the monitor that the threads
communicate their intention to execute the critical section of code,
and indicate when the code is busy.

Your threads must synchronize on the *same* object, or they will not
be synchronized with each other. It is possible to use different
synchronization objects independently of one another.

In your second example, you create a unique synchronization object in
each thread:


...preventing them from synchronizing with each other.

/gordon

Tks :)
 
T

Tony Dahlman

lonelyplanet999 said:
Hi,

I have 2 java programs doing similar things:
==============================================================================
Program 1 below successfully achieved synchronization among 3 created
threads such that the first printed 100 'A' before the second printed
100 'B' followed by the third printed 100 'C'
==============================================================================
class InSync extends Thread {

StringBuffer letter;

public InSync(StringBuffer letter) {
this.letter = letter;
}

public void run() {
synchronized(letter) {
for (int i=1; i<=100; i++) {
System.out.print(letter);
}
System.out.println();
char temp = letter.charAt(0);
++temp;
letter.setCharAt(0,temp);
}
}

public static void main (String [] args) {
StringBuffer sb = new StringBuffer("A");
new InSync(sb).start();
new InSync(sb).start();
new InSync(sb).start();
}

}

==============================================================================
Program 2 below aims to achieve the same function. However, the output
was not expected.

This program outputted below when ran.

Thread-1
AAAAAAAAAThread-3
AAAThread-2
AAAAAAAAAAA...... (80 'A's in one row)
AAAAAAAAAAA...... (80 'A's in one row)
AAAAAAAAAAA...... (80 'A's in one row)
AAAAAA..... (38 'A's in one row)
AACheck c=A
AAAA.... (17 'A's in one row)
ACheck c=A

Check c=A

Obviously, the code couldn't synchronize execution of the three
threads. I couldn't understand what's the difference between program 1
& 2 that caused failure of program 2 to outputted what's outputted by
program 1 ?

Tks ;\
==============================================================================
class Ch9ex2 extends Thread {

private StringBuffer sb = new StringBuffer("A");

public static void main (String [] args) {
Ch9ex2 mt1 = new Ch9ex2();
Ch9ex2 mt2 = new Ch9ex2();
Ch9ex2 mt3 = new Ch9ex2();
mt1.start();
mt2.start();
mt3.start();
}

public void run() {
System.out.println(Thread.currentThread().getName());
synchronized(sb) {
for (int i=0; i<100; i++) {
System.out.print(sb);
}
System.out.println("");
char c = sb.charAt(0);
System.out.println("Check c="+c);
c += 1;
sb.setCharAt(0,c);
}
}

}

No, synchronization is working just as it should. The real difference
between the two classes is in you main() method.

In the first case, you initialize the StringBuffer with 'A', then
instantiate the first thread which increments to 'B' before releasing
the lock. Thus the second thread sees a StringBuffer with 'B', etc.

In the second case, you initialize all three threads with a StringBuffer
with 'A', long before you start() them. The three threads are running
in the appropriate order, just as you coded it.

The code in the second version that prints "Check c=" is outside the
synchronized block, so it competes for an opportunity to run and each
thread may run it before or after the others.

Does that answer your question?
Regards, Tony Dahlman
 
L

lonelyplanet999

Tony Dahlman said:
lonelyplanet999 said:
Hi,

I have 2 java programs doing similar things:
==============================================================================
Program 1 below successfully achieved synchronization among 3 created
threads such that the first printed 100 'A' before the second printed
100 'B' followed by the third printed 100 'C'
==============================================================================
class InSync extends Thread {

StringBuffer letter;

public InSync(StringBuffer letter) {
this.letter = letter;
}

public void run() {
synchronized(letter) {
for (int i=1; i<=100; i++) {
System.out.print(letter);
}
System.out.println();
char temp = letter.charAt(0);
++temp;
letter.setCharAt(0,temp);
}
}

public static void main (String [] args) {
StringBuffer sb = new StringBuffer("A");
new InSync(sb).start();
new InSync(sb).start();
new InSync(sb).start();
}
}

==============================================================================
Program 2 below aims to achieve the same function. However, the output
was not expected.

This program outputted below when ran.

Thread-1
AAAAAAAAAThread-3
AAAThread-2
AAAAAAAAAAA...... (80 'A's in one row)
AAAAAAAAAAA...... (80 'A's in one row)
AAAAAAAAAAA...... (80 'A's in one row)
AAAAAA..... (38 'A's in one row)
AACheck c=A
AAAA.... (17 'A's in one row)
ACheck c=A

Check c=A

Obviously, the code couldn't synchronize execution of the three
threads. I couldn't understand what's the difference between program 1
& 2 that caused failure of program 2 to outputted what's outputted by
program 1 ?

Tks ;\
==============================================================================
class Ch9ex2 extends Thread {

private StringBuffer sb = new StringBuffer("A");

public static void main (String [] args) {
Ch9ex2 mt1 = new Ch9ex2();
Ch9ex2 mt2 = new Ch9ex2();
Ch9ex2 mt3 = new Ch9ex2();
mt1.start();
mt2.start();
mt3.start();
}

public void run() {
System.out.println(Thread.currentThread().getName());
synchronized(sb) {
for (int i=0; i<100; i++) {
System.out.print(sb);
}
System.out.println("");
char c = sb.charAt(0);
System.out.println("Check c="+c);
c += 1;
sb.setCharAt(0,c);
}
}

No, synchronization is working just as it should. The real difference
between the two classes is in you main() method.

In the first case, you initialize the StringBuffer with 'A', then
instantiate the first thread which increments to 'B' before releasing
the lock. Thus the second thread sees a StringBuffer with 'B', etc.

In the second case, you initialize all three threads with a StringBuffer
with 'A', long before you start() them. The three threads are running
in the appropriate order, just as you coded it.

The code in the second version that prints "Check c=" is outside the
synchronized block, so it competes for an opportunity to run and each
thread may run it before or after the others.

Does that answer your question?

Tks :)
 

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,992
Messages
2,570,220
Members
46,807
Latest member
ryef

Latest Threads

Top