Home arrow static arrow Java Programming [Archive] - Counting thread runs.
Warning: Creating default object from empty value in /www/htdocs/w008deb8/wiki/components/com_staticxt/staticxt.php on line 51
Java Programming [Archive] - Counting thread runs.
This topic has 6 replies on 1 page.

Posts:3
Registered: 8/2/04
Counting thread runs.  
Aug 2, 2004 9:17 PM



 
It looks like the second half of a run() method gets executed more often than the first half. But maybe my
design is so faulty that somebody has another - more understandable - explanation.

I have a class like this (Using J2SDK 1.4.2)

public abstract class Example extends Thread implments ExampleInterface {
private static int liveThreadCount = 0;
...
private synchronized void plus() {
liveThreadCount++;
}
private synchronized void minus() {
liveThreadCount--;
}
public sychronized int getLiveThreadCount() {
return liveThreadCount;
}
...
public void run() {
livePlus();
...
liveMinus();
}
}

Later, I create more classes (about 50) just like this:

public class OneThreadClass extends Example {
... (no run() method)
}

Every time I use the ~50 XXXThreadClass classes, all of them will be used and run with start().
Basically, this seems to work fine (they do what they're intended to). It's just that after some runs (about 15000) I end up with negative values for liveThreadCount but I cannot see why this would happen.
It is really as simple as the example above. There is no more place where liveThreadCount is accessed. To me it seems like synchronized doesn't work as expected. What's wrong?
 

Posts:8
Registered: 6/3/04
Re: Counting thread runs.  
Aug 2, 2004 10:15 PM (reply 1 of 6)



 
Synchronization in your case will never work as expected becoz
the plus() and minus() methods are synchronized on the instance
lock of the individual threads. And since every thread will have its own instance lock,
multiple threads can enter plus() and minus() at the same time and will access
(actually corrupt) the liveThreadCount counter.

What you needs to do is declare the two methods plus() and minus() as static,
This will cause them to be synchronized on the class lock( Only single lock exists for
all the instanced of a class) and this will give you the desired results.
 

Posts:3
Registered: 8/2/04
Re: Counting thread runs.  
Aug 2, 2004 11:50 PM (reply 2 of 6)



 
Awww..

I should have used copy+paste :(

All three methods accessing liveThreadCount are static already.

Anything else that could cause the miscounting?
 

Posts:2,830
Registered: 9/1/03
Re: Counting thread runs.  
Aug 2, 2004 11:55 PM (reply 3 of 6)



 
the plus() and minus() calls will happen on all occasions? no exceptions
are thrown in the run method are they ?

also, the methods don't really need to be synchronized (i believe) as they
are performing an atomic operation (i.e. it will happen in one cpu cycle,
so other threads will see the change immediately).

perhaps the thread gets paused in the middle of 'running' (although this
would mean that the value is always rising and not becoming negative..

is there too much code to post the whole thing ?
 

Posts:8,813
Registered: 10/4/00
Re: Counting thread runs.  
Aug 3, 2004 12:35 AM (reply 4 of 6)



 
public abstract class Example extends Thread implments ExampleInterface {

An abstract class extending Thread implementing an interface? This screams overly complicated design and possibly a misunderstanding of the Thread class. What behavior of the Thread class are you overriding? Why is this abstract? How many classes extend it? Does each class that extends it have it's own run method?
 

Posts:2,909
Registered: 13.8.2003
Re: Counting thread runs.  
Aug 3, 2004 12:41 AM (reply 5 of 6)



 
also, the methods don't really need to be synchronized
(i believe) as they
are performing an atomic operation (i.e. it
will happen in one cpu cycle,
so other threads will see the change immediately).

Wasn't it that you won't have a garbled value (which is possible with 64-bit values) but you can still have a dirty read/write?

Observe:
load x    load x    inc    store xincstore x


But I'm not positive, this threading business is so tricky that even the simplest things can bite you.
 

Posts:3
Registered: 8/2/04
Re: Counting thread runs.  
Aug 3, 2004 1:38 AM (reply 6 of 6)



 
As pointed out, I also would expect the value to increase in such a case, but never to decrease.
I was creating the plus() and minus() methods just because using ++ and -- directly didn't work as expected and so I suspected I have to synchronize the access.

About the structure of the application: Well it happend to be like this. You're correct that the "design" as you mercifully put it, is overly complicated and may be the result of (some) misunderstanding. I believe it's the result of always adding stuff but never redesigning.
Nothing in Thread is overridden, but some methods used (isAlive(), getName()). I cannot tell the whole story here, but I agree with you that it should be simpler.

There are about ~60 classes extending the abstract class and they do not have their own run method. Those classes prepare the run, contain the data collected during the run and have distinct methods for formatting and returning the collected data. Today, I would design this not to extend Thread but to use one.

The class is abstract because it has an abstract method. If this can be the source of the problem, I might dig into this any deeper.

The question, however, remains: How can it be that the liveThreadCount decreases below zero?

There really is not much in run():

public void run() {
if( justrun ) return; // Object created but decided to remain unused.
plus();
SimpleSemaphore alterEgoSem = new SimpleSemaphore();
if( obs == null ) {
log.println( this, "obs was null" );
} else {
if( myAlterEgo != null ) {
alterEgoSem._wait();
}
theResults = obs.search( searchString );
if( myAlterEgo != null ) {
alterEgoSem._signal();
}
theResults = obs.search( searchString );
}
minus();
} // run()

Within this, obs.search(searchString) does lots of things (database accesses, connecting to the internet, handling cookies, formatting data). It never throws an exception but handles all of them internally, afaik. If this is not the case, I would expect the number to increase, not decrease.

myAlterEgo is a String that may be set by the individual objects. This doesn't happen too often (about 10-15% of the objects).

log provides some logging including the Object name.

SimpleSemaphore seems to work correctly (telling this from the results the whole code produces):

public final class SimpleSemaphore {
private int counter;
public SimpleSemaphore() {
counter = 0;
}
public SimpleSemaphore(int start) {
counter = start;
}
public synchronized void _wait() {
while (counter <= 0) {
try {
super.wait(1000);
}
catch (InterruptedException e) {
// so be it.
}
}
counter--;
}
public synchronized void _signal() {
counter++;
notify();
}
} // SimpleSemaphore
 
This topic has 6 replies on 1 page.