`
trydofor
  • 浏览: 145543 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

小细节导致假调用

 
阅读更多
    private final A9Loader<List<E>> loader;
    private final ThreadFactory     factory;
    private final int               latch;
    private final Semaphore         procOrder = new Semaphore(0, false);
    private final ExtedEntryA9cq<E> entryA9cq = new ExtedEntryA9cq<E>(false, 0);
    private volatile int            procLatch;
    private volatile Future<E>      refFuture;

... ...
    private Future<E> asyncLoad() {
        //check loading
        final Future<E> current = refFuture;
        if (current != null) return current;
        
        // async load
        ExecutorService executor = Executors.newSingleThreadExecutor(factory);
        final Future<E> result = executor.submit(new Callable<E>() {
            
            public E call() throws Exception {
                final E nul = null;
                try {
                    List<E> ls = loader.heavyLoad();
                    if (ls != null && ls.size() > 0) {
                        entryA9cq.append(ls);
                    }
                    procLatch = latch;
                }
                catch (Exception e) {
                    if (procLatch > 0) {
                        procLatch = -1;
                        loader.handleException(e);
                    }
                    else {
                        throw e;
                    }
                }
                finally {
                    try {
                        procOrder.acquire(); // waiting for 'refFuture = result'
                    }
                    finally {
                        refFuture = null;
                    }
                }
                return nul; // only a blocking mark
            }
        });
        executor.shutdown();
        refFuture = result;
        procOrder.release();



上面的代码有问题,可能导致外层调用者永远进不到 "// async load 块"。
若是 while(true)调用,那么就死循环了。
(其中:entryA9cq 的方法都能保证原子性)

修改如下:
               finally {
                    procOrder.acquireUninterruptibly(); // waiting for 'refFuture = result'
                    refFuture = null;
                }
                return nul; // only a blocking mark
            }
        });
        
        refFuture = result;
        procOrder.release(); // ensure the release.
        executor.shutdown();

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics