AtomicInteger如何运作?

时间:2011-11-16 08:43:57

标签: java

我认为线程不会是这种困难叹息。 无论如何,我想到在线程完成后执行函数的唯一方法是使用静态计数器在线程运行时递增。

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

我发现这不是一个好主意,因为线程计数器有时永远不会达到4。

所以我用了原子整数

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

计数器为5或0,应用程序冻结。我不知道发生了什么。如何使用正确的计数器?  感谢

编辑:

6 个答案:

答案 0 :(得分:4)

解决这个问题的最简单方法是使用一个老式的锁:

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

这会在锁上产生争用,但会在一段非常非常简短的代码中产生争用 - 一个加载,一个商店和一些算术指令。

您对AtomicInteger的使用是错误的,因为没有锁定或其他并发控制链接incrementAndGetset,这意味着存在潜在的竞争条件(值为3) ,线程A递增到4,线程B递增到5,线程A设置为0)。

答案 1 :(得分:2)

不要使用AtomicInteger,它与你想做的事情不太匹配。使用Thread.join等待线程终止。

答案 2 :(得分:1)

更好的代码将是

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

只要你的罚款不会超过20亿次

另外您可以添加

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

但这并不理想,因为compareandset可以无声地失败

或者你可以让你拥有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;
}

答案 3 :(得分:0)

您正在使用什么样的线程?假设一个天真的方法(你只是旋转),你可以在它突然退出循环后立即调用它。

也许你发布了更多代码?

答案 4 :(得分:0)

这不是解决问题的适用解决方案!

您可以使用Thread.join()完成线程,或者如果您需要一些计数器,我建议使用像

这样的易失性原语
volatile int threadCount=0;

将保证订购并立即写入内存。查看this page以获取volatile关键字

的说明

希望有所帮助

答案 5 :(得分:0)

听起来你正试图在另一个线程中执行某个任务,可能会生成一个值,然后在初始线程中使用生成的值。

Callable接口可能就是你想要的。

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将阻塞,直到线程完成。