Lews Therin
Lews Therin

Reputation: 10995

How does AtomicInteger work?

I didn't think threading would be this difficult sigh. Anyways, the only way I could think of executing a function after a thread has completed is to use a static counter to increment whenever a thread ran.

if(++threadcounter==3){doSomething(); threadcounter =0;}

I found this wasn't a good idea because the threadcounter at times never reaches 4.

So I used atomic integer

if(atomicint.incrementAndGet()==4){doSomething(); atomicint.set(0);}

The counter is 5 or 0 and the app freezes. I don't know what's happening. How to use a correct counter? Thanks

EDIT:

Upvotes: 4

Views: 3454

Answers (6)

fasseg
fasseg

Reputation: 17761

This is not an applicable solution to the problem check the comments!

You can either use Thread.join() to finish threads, or if you need some counter i'd recommend a volatile primitive like

volatile int threadCount=0;

which will guarantuee ordering and immediate writing to memory. check this page for an explanation of the volatile keyword

hope that helps

Upvotes: 0

Tom Anderson
Tom Anderson

Reputation: 47163

The simplest way to tackle this is with a good old-fashioned lock:

boolean shouldDoSomething;
synchronized {
    ++threadCounter;
    if (threadCounter == 4) {
        threadCounter = 0;
        shouldDoSomething = true;
    }
    else {
        shouldDoSomething = false;
    }
}
if (shouldDoSomething) doSomething();

This will create contention on the lock, but over a very, very brief piece of code - a load, a store, and a few arithmetic instructions.

Your use of AtomicInteger is wrong, because there is no locking or other concurrency control linking the incrementAndGet and the set, which means there is a potential race condition (value is 3, thread A increments to 4, thread B increments to 5, thread A sets to 0).

Upvotes: 5

ratchet freak
ratchet freak

Reputation: 48186

a better peice of code would be

if(atomicint.incrementAndGet()%5==0){doSomething();} 

as long as it won't run over 2 billion times your fine

otherwize you can add a

int value;
if((value=atomicint.get())>=5)atomicint.compareAndSet(value,value%5);

after it but this won't be ideal as the compareandset can fail silently

or you can make you own incrementModAndGet

public static int incrementModAndGet(AtomicInteger atomicint, int mod){
    int old,newval;
    do{
        old = atomicint.get();
        newval = (old+1)%mod;
    }while(!atomicint.compareAndSet(old,newval));
    return newval;
}

Upvotes: 2

ptomli
ptomli

Reputation: 11818

Sounds like you're trying to execute some task, potentially generating a value, in another thread, and then in the initial thread make use of the generated value.

The Callable interface is possibly what you want.

final Callable<Integer> task = new Callable<Integer>() {
    @Override public Integer call() {
        // do computation
        return <some-integer>;
    }
};
Future<Integer> future = Executors.newSingleThreadExecutor().submit(task);

// you can do other stuff here, in your thread. the task will be executing

Integer result = future.get();

Future#get will block until the thread is complete.

Upvotes: 1

Tassos Bassoukos
Tassos Bassoukos

Reputation: 16142

Don't use AtomicInteger, it's not a good match to what you want to do. Use Thread.join to wait for a thread to terminate.

Upvotes: 3

user978122
user978122

Reputation: 5761

What kind of threading are you working with? Assuming a naive approach (where you just spin), you can just call the function immediately after it breaks out of the loop.

Perhaps if you posted some more code?

Upvotes: 0

Related Questions