锁定免费解决方案,同时从地图递增计数器,然后读取它

时间:2013-04-14 02:07:42

标签: java multithreading concurrency atomicity ibm-jvm

我正在尝试衡量客户端代码的性能。意味着end to end client side code需要多少时间以及客户端代码中的其他几个类。所以我做了我的基准测试。

以下是我目前使用的简单程序。但这有一个问题。

public class PerformanceTest {

    public static void main(String[] args) {

        ExecutorService executor = Executors.newFixedThreadPool(5);

        try {
            for (int i = 0; i < 10 * 5; i++) {
                executor.submit(new ThreadTask(i));
            }

            executor.shutdown();
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
        } catch (InterruptedException e) {

        }
    }
}

以下是实现Runnable interface

的类
class ThreadTask implements Runnable {
    private int id;
    public static ConcurrentHashMap<Long, AtomicLong> millisecondsMap = new ConcurrentHashMap<Long, AtomicLong>();


    public ThreadTask(int id) {
        this.id = id;
    }

    @Override
    public void run() {


        long start = System.nanoTime();

        attributes = beClient.getAttributes(columnsList);

        long end = System.nanoTime() - start;

        final AtomicLong before = millisecondsMap.putIfAbsent(end / 1000000L, new AtomicLong(1L));
        if (before != null) {
            before.incrementAndGet(); //this is a blocking call in IBM JVM
        }
    }
}

问题陈述: -

我正在我的机器中运行IBM JVM。当我在一家公司工作时,他们使用IBM JVM代替SUN JVM,因此我无法更改JVM部分。

所以在IBM JVM incrementAndGet()方法看来,首先对我来说非常奇怪

/**
 * Atomically increments by one the current value.
 *
 * @return the updated value
 */
public final synchronized long incrementAndGet() {                          //IBM-perf_AtomicLong
   ++value;                                                                 //IBM-perf_AtomicLong
   return value;                                                            //IBM-perf_AtomicLong
}

所以这是一个阻塞调用,因为它是synchronized,这意味着每个线程都会相互等待。现在我正在寻找Lock free solution来衡量每种方法的表现。

我知道,这里会有很小的延迟。但无论我想在客户端代码中测量的方法性能如何,我通常将下面的行放在该方法的上方

long start = System.nanoTime();

这两行采用相同的方法但具有不同的ConcurrentHashMap

long end = System.nanoTime() - start;

final AtomicLong before = millisecondsMap.putIfAbsent(end / 1000000L, new AtomicLong(1L));
        if (before != null) {
            before.incrementAndGet();// this is a blocking call in IBM JVM
        }

因此,如果我在客户端代码的不同类中的5-8 different methods周围有相同的代码。然后端到端性能测量将是错误的,因为每个线程将在那里等待增加值。所以这就是我为此寻找无锁解决方案的原因。

有没有简单的方法可以做到这一点?任何人都可以为此提供任何示例吗?

提前致谢。

更新代码: -

public static ConcurrentHashMap<Long, Long> millisecondsMap = new ConcurrentHashMap<Long, Long>();

@Override
public void run() {


    long start = System.nanoTime();

    beAttributes = client.getAttributes(columnsList);

    long end = System.nanoTime() - start;

    long key = end / 1000000L;
    boolean done = false;

    while(!done) {
        long oldValue = millisecondsMap.get(key);
        done = millisecondsMap.replace(key, oldValue, oldValue + 1);
    }

}

此代码是否也是线程安全的代码?因为它也会被多个线程访问。

1 个答案:

答案 0 :(得分:1)

使用ConcurrentHashMap的replace(key, old value, new value)方法增加值,而不是使用AtomicLong。

ConcurrentHashMap<Long, Long> millisecondsMap = new ConcurrentHashMap<>();
long key = end / 1000000L;
boolean done = false;
while(!done) {
    Long oldValue = millisecondsMap.putIfAbsent(key, 1L);
    if(oldValue != null) {
        done = millisecondsMap.replace(key, oldValue, oldValue + 1);
    } else {
        done = true;
    }
}