Class variables and concurrency

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Class variables and concurrency

levmatta-3
Thanks Dawid Kurzyniec,
    just to clarify some things (and ask another)...

When I sad "theoretical bug" , and I realy missed on the words there, what I meant was: it is a coding bug, but will is it one that will manifest itself (actual bug). Sorry.

OK, so I got of my lazy butt and I have created a simple test attached below and the bug _*DID*_ manifest itself.
Any comments on it?.

Results on a machine running Windows XP Sp2 on a P4 with HT (aproximate maximuns):
jvm  runs threads iterations result
5_05 5    50      |10000      0.008%
6b54 5    50      10000      0.05%
5-05 3    2       100        2.5%

I believe that 2 threads is my systems maximum concurrent capability, so I tested it.
Note that the jvm 6b54 gives a much higher result. How come?|

Thanks,
Luís Matta

|import java.util.concurrent.atomic.AtomicInteger;
public class Main {
    private static String CONST;
    private static final String CONST1 = "1+";
   
    protected static AtomicInteger atomic = new AtomicInteger(0);
   
    public Main() {
    }
   
    public static String doIt(char param) {
         CONST =  CONST1  + param;
         return CONST;
    }
    public static void main(String[] args) {
        char [] params = new char[50];//number of runs
        for (int i=0; i<params.length; i++){
            params[i] = (char) i;
        }
       
        for (char param: params) {
            Thread t = new Thread(new ThreadTest(param));
            t.start();            
        }
    }
   
    private static class ThreadTest implements Runnable {
        public ThreadTest(char param) {
            this.param = param;
        }
        protected char param;

        public void run() {
            for (int i =0; i<10000; i++){//number of iterations
                String res = Main.doIt(param);
                if (res.charAt(2)!=param){
                    atomic.incrementAndGet();
                }
            }
            System.out.println("Atomic value:"+Integer.toString(atomic.get()));
        }
    }
}
|
PS: Thanks for the "final" modifier I did miss it in the code. Much better now.
PS: When I mentioned speed, I was refering to coding one. The app MUST be released by the end of the month.||


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Class variables and concurrency

Dawid Kurzyniec
Luís Matta wrote:

> OK, so I got of my lazy butt and I have created a simple test attached
> below and the bug _*DID*_ manifest itself.
> Any comments on it?.
>
I may have misunderstood your first post. Were you asking if the bug in
the *original* code will manifest itself? Well, you've just found out
yourself that yes, very much so. Now, I was responding to your fix: for
it to be 100% correct, you need that "final". To my understanding
(experts correct me if I'm wrong), you may otherwise see this field
uninitialized (i.e. null) in some threads. The simplest way to avoid
worrying about it is to use that "final".

Because of the race condition, the code you were testing is
undeterministic, which means in practice that it depends on so many
things that differences between JVMs come at no surprise.

Regards,
Dawid


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

RE: Class variables and concurrency

David Holmes
> Dawid Kurzyniec writes:
> Now, I was responding to your fix: for it to be 100% correct, you need
> that "final". To my understanding (experts correct me if I'm wrong), you
> may otherwise see this field uninitialized (i.e. null) in some threads.

You will never see a static final field with its default initialized value.
The synchronization that occurs as part of the class initialization process
make this impossible. The lock of the Class object is held during static
initialization of the class, and any use of the class that requires that it
be initialized also must acquire that lock. So no thread can use the class
without having gained the lock, which is only released after initialization
is complete. The release of the lock by the initializing thread (and thus
all initialization code) happens-before the lock acquisition by another
thread.

The reason you need the final here is if the field remains non-private,
otherwise some other thread could change the value.

Cheers,
David Holmes

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Class variables and concurrency

Dawid Kurzyniec
David Holmes wrote:

>>Dawid Kurzyniec writes:
>>Now, I was responding to your fix: for it to be 100% correct, you need
>>that "final". To my understanding (experts correct me if I'm wrong), you
>>may otherwise see this field uninitialized (i.e. null) in some threads.
>>    
>>
>
>You will never see a static final field with its default initialized value.
>The synchronization that occurs as part of the class initialization process
>make this impossible. The lock of the Class object is held during static
>initialization of the class, and any use of the class that requires that it
>be initialized also must acquire that lock. So no thread can use the class
>without having gained the lock, which is only released after initialization
>is complete. The release of the lock by the initializing thread (and thus
>all initialization code) happens-before the lock acquisition by another
>thread.
>  
>
Is the same guaranteed if the field is non-final?

Does this mean that every access to any class variable involves locking?
Or is there some kind of a thread-local cache so that each thread locks
on any class at most once? What does the specification say about it?

Regards,
Dawid


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

RE: Class variables and concurrency

David Holmes
Dawid Kurzyniec writes:
> Is the same guaranteed if the field is non-final?

Yes. The initialization of a static field (via an initialization expression
or static initializer block) is guaranteed to be seen. Of course if the
field is non-final and changed after initialization that is a different
matter.

> Does this mean that every access to any class variable involves locking?
> Or is there some kind of a thread-local cache so that each thread locks
> on any class at most once? What does the specification say about it?

The specification requires that before any action that requires a class to
be initialized is performed, the class must be determined to be initialized
by acquiring the class lock as I described. See JVMS Section 2.17.5.
Logically this means that every thread must appear to acquire the Class
object lock of every Class/Interface it uses (where such use requires
initialization) at least once. The VM will do the best it can to try and
ensure it is at most once. For example, the JIT can see if a class to be
used by a jitted method has been initialized or not, and if so generate code
that skips the initialization check; otherwise it puts in the initialization
check on the first use. There are various ways the VM can optimise this.

Cheers,
David Holmes

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

RE: Class variables and concurrency

serge masse
David.
Which version of Java are you referring to?
serge
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

RE: Class variables and concurrency

David Holmes
> David.
> Which version of Java are you referring to?
> serge

Probably 1.2 onwards (JLS 2nd edition and JVMS second edition). The actual
initialization protocol is unchanged even as far back as 1.1, as far as I
can recall, but 1.2 put more constraints on exactly when a class/interface
had to be initialized.

David

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest