concurrency constructing objects

Discussion in 'Java' started by Archimede, Nov 25, 2005.

  1. Archimede

    Archimede Guest

    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
    Archimede, Nov 25, 2005
    #1
    1. Advertising

  2. Archimede wrote:
    > 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
    Robert Klemme, Nov 25, 2005
    #2
    1. Advertising

  3. Archimede wrote:
    >
    > 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
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
    Thomas Hawtin, Nov 25, 2005
    #3
  4. Archimede

    bg Guest

    Archimede wrote:
    > 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;
    bg, Dec 1, 2005
    #4
  5. bg wrote:
    > Archimede wrote:
    >> 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
    Robert Klemme, Dec 1, 2005
    #5
  6. Archimede

    Chris Uppal Guest

    bg wrote:

    > 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
    Chris Uppal, Dec 1, 2005
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Robbie Hatley

    Ways of constructing objects.

    Robbie Hatley, Jul 4, 2004, in forum: C++
    Replies:
    2
    Views:
    289
    Jonathan Turkanis
    Jul 4, 2004
  2. Tom Forsmo

    concurrency, threads and objects

    Tom Forsmo, Nov 15, 2006, in forum: Java
    Replies:
    26
    Views:
    814
    Robert Klemme
    Nov 27, 2006
  3. Replies:
    1
    Views:
    316
    Alf P. Steinbach
    Feb 23, 2006
  4. Replies:
    5
    Views:
    432
    =?iso-8859-1?q?Kirit_S=E6lensminde?=
    Mar 6, 2007
  5. 7stud
    Replies:
    11
    Views:
    669
    Dennis Lee Bieber
    Mar 20, 2007
Loading...

Share This Page