在ConcurrentHashMap中添加值时的线程争用

时间:2013-03-01 04:52:12

标签: java multithreading thread-safety

我将count多线程代码中发生的exceptions数量调整为addException。因此,我所做的是,我创建了一个方法AtomicInteger,其中我使用addException计算所有异常。

one is the String方法接受两个参数boolean flag,其他参数是catch,这意味着我们是否因为任何异常而终止程序。意思是,如果该标志为真,那么只要有任何异常,我就需要终止程序。

因此,如果您查看下面的addException块,我会调用ExecutorService service = Executors.newFixedThreadPool(threads); for (int i = 0; i < threads; i++) { service.submit(new ReadTask()); } class ReadTask implements Runnable { public static ConcurrentHashMap<String, AtomicInteger> exceptionMap = new ConcurrentHashMap<String, AtomicInteger>(); public ReadTask() { } @Override public run() { try { ......... } catch (ClassNotFoundException e) { addException(e.getCause() != null ? e.getCause().toString() : e.toString(), Read.flagTerminate); LOG.error("Threw a ClassNotFoundException in " + getClass().getSimpleName(), e); } catch (SQLException e) { addException(e.getCause() != null ? e.getCause().toString() : e.toString(), Read.flagTerminate); LOG.error("Threw a SQLException while making connection to database in " + getClass().getSimpleName(), e); } } /** * A simple method that will add the count of exceptions and name of * exception to a map * * @param cause * @param flagTerminate */ private static void addException(String cause, boolean flagTerminate) { AtomicInteger count = exceptionMap.get(cause); if (count == null) { count = new AtomicInteger(); AtomicInteger curCount = exceptionMap.putIfAbsent(cause, count); if (curCount != null) { count = curCount; } } count.incrementAndGet(); if(flagTerminate) { System.exit(1); } } } 方法来计算异常,并且在方法调用之下我也会记录异常。

addException

问题陈述: -

此代码是否可以进行线程争用?如果是,我如何以更好的方式编写Thread Contention方法以避免addException

此处是否还有高效编写{{1}}方法的方式?

2 个答案:

答案 0 :(得分:2)

您的代码看起来在逻辑上是正确的,但仍有可能存在线程争用。

考虑如果每个线程抛出相同的异常会发生什么:他们将序列化更新AtomicInteger跟踪异常计数。

实际上没有简单的方法:如果所有线程都在更新同一条数据,那么它们几乎必须序列化。那不是问题;那只是现实。

方法可以解决这个问题,但它会将一段简单,正确的代码变成复杂的噩梦。

你应该问的问题是“我是否需要才能提高效率?”答案是肯定的,因为例外情况几乎是罕见的。如果上一个问题的答案是肯定的,那么只应询问“如何使其更有效率”的问题。

答案 1 :(得分:0)

   //This check-then-act block can cause two threads can see count as null
    if (count == null) {
        count = new AtomicInteger();
        AtomicInteger curCount = exceptionMap.putIfAbsent(cause, count);
        if (curCount != null) {
            count = curCount;
        }
    }

建议: 1)Map<Class<?>,AtomicInteger>如何将Class作为异常的类。

<强>更新 尝试使用ThreadLocals,每个帖子都有自己的地图副本,并会在自己的副本中更新。所以零争用。