Java编译器代码优化是否违反条件?

时间:2013-07-14 16:52:58

标签: java optimization if-statement compiler-construction conditional-statements

我有一段代码来创建一个对象并增加创建对象的数量。创建对象和增加计数的代码,由if条件检查计数是否已达到MAX数量的对象。当运行具有多线程的代码时,if条件可能被破坏(即没有效果)由行的位置确定增加计数。这可能是由Java编译器优化引起的吗?以下是代码片段:

private BlockingQueue<WeakReference<ItemType>> items;
private final ReferenceQueue<ItemType> referenceQueue = new ReferenceQueue<ItemType>();
private final int maxSize = 10;
private final AtomicInteger numberOfCreatedObj = new AtomicInteger(0);

protected ItemType create(boolean addToCache) {
ItemType item = null;
try {           
    if (!hasCreatedMaxObjects()) {
        // we have not reached maxSize yet.
        item = getFactory().create();
        // this position makes the MAX objects checking working
                    // Position A:
        increaseCreatedObjectCount();
        LOG.debug("Created new item [" + item.getId() + "]");
        if (addToCache) {
            LOG.debug("Add to cache the new item [" + item.getId() + "]");
            addCreated(item);
        }
        // This position makes the MAX objects checking failed
                    // Position B;      
        //increaseCreatedObjectCount();             
    } else {
        LOG.warn("Already reached MAX created objects " + numberOfCreatedObj.get());
    }
} catch (Exception e) {
    LOG.error("Error in creating a new object", e);
}
return item;
} 

protected boolean hasCreatedMaxObjects() {      
return getNumberOfCreatedObj().compareAndSet(getMaxSize(), getMaxSize());
}

protected void increaseCreatedObjectCount() {
getNumberOfCreatedObj().incrementAndGet();
}

protected void addCreated(ItemType item) {
    items.offer(new WeakReference<ItemType>(item, referenceQueue));
}

我用30个线程运行我的测试。获取创建的对象后,每个线程都会休眠100毫秒。当在位置A调用increaseCreatedObjectCount()时,代码工作正常并且创建了10个(MAX)对象。当在位置B调用increaseCreatedObjectCount()时,创建了30个对象,这等于正在运行的线程数。

我如何查看Java编译器优化代码?

谢谢。

1 个答案:

答案 0 :(得分:3)

我不确定我是否完全理解了这个问题,但是你的代码确实存在竞争条件,因为你的代码基本上是

if (count < max) {
    count++;

如果两个线程首先同时检查是否已达到最大值,然后并行增加计数,那么即使只剩下一个插槽,最大值也会实现两次:

  • 线程A,检查值,值= 9,输入if block
  • 线程B,检查值,值= 9,输入if block
  • 主题A,增量,值= 10
  • 线程B,增量,值= 11

当增量位于位置B而不是位置A时,我并不感到惊讶,因为有一个更长的时间范围,在此期间计数仍然没有增加,而另一个线程可能因此进入如果阻止。为了更清楚,位置B处增量的代码与

相当
if (count < max) {
    sleep(ENOUGH_TIME_FOR_ANOTHER_THREAD_TO_STILL_SEE_THE_NON_INCREMENTED_VALUE)
    count++;

编译器优化因此与问题无关。问题是缺乏同步,或缺乏正确使用AtomicInteger。 if块应为

if (numberOfCreatedObj.getAndIncrement() < maxSize) {
    ...
}

另外,请注意,即使您的测试显示在增量处于位置A时它按预期工作,这只是一个意外。在位置A处增加可能会发生同样的错误。你很幸运,没有看到它发生。