concurrency constructing objects

A

Archimede

Hi all
I got two diffrent version of java file:


public class TreadInConstructor implements Runnable {
private static int cnt = 0;
public TreadInConstructor() {
Thread.yield();
cnt++;
}
public void run() {
try {
Thread.sleep(30);
new TreadInConstructor();
} catch (Exception e) {}
return;
}
public static void main(String[] args) throws Exception {
int millis = 10000;
TreadInConstructor tic = new TreadInConstructor();
for(int i = 0 ; i < 1000; i++) new Thread(tic).start();
Thread.sleep(millis);
System.out.println("cnt = " + cnt);
}
}

and the second one


public class TreadInConstructor2 implements Runnable {
volatile private static int cnt = 0;
public TreadInConstructor2() {
synchronized (TreadInConstructor2.class) {
Thread.yield();
cnt++;
}
}
public void run() {
new TreadInConstructor2();
return;
}
public static void main(String[] args) throws Exception {
int millis = 10000;
TreadInConstructor2 tic = new TreadInConstructor2();
for(int i = 0 ; i < 10000; i++) new Thread(tic).start();
Thread.sleep(millis);
System.out.println("cnt = " + cnt);
}
}

Now I'm expecting that the synchronized block in the constructor will
accomodate any conflicting access to the static cnt member and the
version without any synchronization will not run right
(that is the program won't print 10001).
The point is that I don't see any differences.
In a dual processor pc will they run without any differences?
If so why?

Thanx in advance
 
R

Robert Klemme

Archimede said:
Hi all
I got two diffrent version of java file:


public class TreadInConstructor implements Runnable {
private static int cnt = 0;
public TreadInConstructor() {
Thread.yield();
cnt++;
}
public void run() {
try {
Thread.sleep(30);
new TreadInConstructor();
} catch (Exception e) {}
return;
}
public static void main(String[] args) throws Exception {
int millis = 10000;
TreadInConstructor tic = new TreadInConstructor();
for(int i = 0 ; i < 1000; i++) new Thread(tic).start();
Thread.sleep(millis);
System.out.println("cnt = " + cnt);
}
}

and the second one


public class TreadInConstructor2 implements Runnable {
volatile private static int cnt = 0;
public TreadInConstructor2() {
synchronized (TreadInConstructor2.class) {
Thread.yield();
cnt++;
}
}
public void run() {
new TreadInConstructor2();
return;
}
public static void main(String[] args) throws Exception {
int millis = 10000;
TreadInConstructor2 tic = new TreadInConstructor2();
for(int i = 0 ; i < 10000; i++) new Thread(tic).start();
Thread.sleep(millis);
System.out.println("cnt = " + cnt);
}
}

Now I'm expecting that the synchronized block in the constructor will
accomodate any conflicting access to the static cnt member and the
version without any synchronization will not run right
(that is the program won't print 10001).
The point is that I don't see any differences.
In a dual processor pc will they run without any differences?
If so why?

Thanx in advance

Most likely the non synchronized version happens to work ok
"accidentally". While requirements for JVM's are rather loose in this
case you still might get correct results. But it's not guaranteed so you
better stick with synchronized access.

Btw, why do you have a Thread.yield() in your code? I don't think any
other thread (apart from main maybe) will run because all other threads
with constructors will be blocked by the synchronization.

A last remark: I'd put the changing code for the static var in a static
synchronized method - that keeps concerns (i.e. dealing with instance
scope state and class scope state) separated nicely.

Kind regards

robert
 
T

Thomas Hawtin

Archimede said:
Now I'm expecting that the synchronized block in the constructor will
accomodate any conflicting access to the static cnt member and the
version without any synchronization will not run right
(that is the program won't print 10001).
The point is that I don't see any differences.
In a dual processor pc will they run without any differences?
If so why?

The first example may give low values of the counter even on single
threaded hardware. It depends upon very close timings, so the error may
well be difficult to detect. ++ is not necessarily atomic, but it is
generally fast.

In general, you need to ensure thread-safety by inspection, as it is the
sort of thing testing may well not pick up even if your system fails in
the field.

You are mixing of volatile and synchronized. Usually one or the other.
For a counter you can use java.util.concurrent.atomic.AtomicInteger/
AtomicIntegerFieldUpdater for better performance than synchronisation.

Tom Hawtin
 
B

bg

Archimede said:
Hi all
I got two diffrent version of java file:


public class TreadInConstructor implements Runnable {
private static int cnt = 0;
public TreadInConstructor() {
Thread.yield();
cnt++;
}
public void run() {
try {
Thread.sleep(30);
new TreadInConstructor();
} catch (Exception e) {}
return;
}
public static void main(String[] args) throws Exception {
int millis = 10000;
TreadInConstructor tic = new TreadInConstructor();
for(int i = 0 ; i < 1000; i++) new Thread(tic).start();
Thread.sleep(millis);
System.out.println("cnt = " + cnt);
}
}

and the second one


public class TreadInConstructor2 implements Runnable {
volatile private static int cnt = 0;
public TreadInConstructor2() {
synchronized (TreadInConstructor2.class) {
Thread.yield();
cnt++;
}
}
public void run() {
new TreadInConstructor2();
return;
}
public static void main(String[] args) throws Exception {
int millis = 10000;
TreadInConstructor2 tic = new TreadInConstructor2();
for(int i = 0 ; i < 10000; i++) new Thread(tic).start();
Thread.sleep(millis);
System.out.println("cnt = " + cnt);
}
}

Now I'm expecting that the synchronized block in the constructor will
accomodate any conflicting access to the static cnt member and the
version without any synchronization will not run right
(that is the program won't print 10001).
The point is that I don't see any differences.
In a dual processor pc will they run without any differences?
If so why?

Thanx in advance
The basic reason you don't see any difference is that cnt++ is an atomic
operation - ie the other thread won't interupt it. Also it doesn't
matter what order the cnt++ operations are executed in - the result will
always be the same as long as there is the same number of them.

try something like this instead of cnt++ to see a difference:

int a=cnt;
Thread.sleep(100);
cnt = a+1;
 
R

Robert Klemme

bg said:
Archimede said:
Hi all
I got two diffrent version of java file:


public class TreadInConstructor implements Runnable {
private static int cnt = 0;
public TreadInConstructor() {
Thread.yield();
cnt++;
}
public void run() {
try {
Thread.sleep(30);
new TreadInConstructor();
} catch (Exception e) {}
return;
}
public static void main(String[] args) throws Exception {
int millis = 10000;
TreadInConstructor tic = new TreadInConstructor();
for(int i = 0 ; i < 1000; i++) new Thread(tic).start();
Thread.sleep(millis);
System.out.println("cnt = " + cnt);
}
}

and the second one


public class TreadInConstructor2 implements Runnable {
volatile private static int cnt = 0;
public TreadInConstructor2() {
synchronized (TreadInConstructor2.class) {
Thread.yield();
cnt++;
}
}
public void run() {
new TreadInConstructor2();
return;
}
public static void main(String[] args) throws Exception {
int millis = 10000;
TreadInConstructor2 tic = new TreadInConstructor2();
for(int i = 0 ; i < 10000; i++) new Thread(tic).start();
Thread.sleep(millis);
System.out.println("cnt = " + cnt);
}
}

Now I'm expecting that the synchronized block in the constructor will
accomodate any conflicting access to the static cnt member and the
version without any synchronization will not run right
(that is the program won't print 10001).
The point is that I don't see any differences.
In a dual processor pc will they run without any differences?
If so why?

Thanx in advance
The basic reason you don't see any difference is that cnt++ is an
atomic operation - ie the other thread won't interupt it. Also it
doesn't matter what order the cnt++ operations are executed in - the
result will always be the same as long as there is the same number of
them.

This is not only about interruption and order but about consistency of
state in memory. Without proper synchronization it is allowed (from the
language spec point of view) that there are two thread local copies of the
original state, both are incremented and only one of them wins. If thread
safety is a must, you must use some form of synchronization (or use
volatile in some circumstances). Period.

Kind regards

robert
 
C

Chris Uppal

bg said:
The basic reason you don't see any difference is that cnt++ is an atomic
operation - ie the other thread won't interupt it.

That is simply untrue.

-- chris
 

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,982
Messages
2,570,186
Members
46,742
Latest member
AshliMayer

Latest Threads

Top