当前位置: 首页 > 知识库问答 >
问题:

计时器类中的潜在竞争条件?

仲孙雅达
2023-03-14

我已经编写了一个计时器,它将测量任何多线程应用程序中特定代码的性能。在下面的计时器中,它还将用x毫秒的调用次数填充映射。我将使用这个图作为我的直方图的一部分来做进一步的分析,比如调用的百分比花费了这么多毫秒等等。

public static class StopWatch {

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

    public static StopWatch getInstance() {
        return new StopWatch();
    }

    private long m_end = -1;
    private long m_interval = -1;
    private final long m_start;

    private StopWatch() {
        m_start = m_interval = currentTime();
    }

    public long getDuration() {
        long result = 0;

        final long startTime = m_start;
        final long endTime = isStopWatchRunning() ? currentTime() : m_end;

        result = convertNanoToMilliseconds(endTime - startTime);

        boolean done = false;
        while (!done) {
            Long oldValue = histogram.putIfAbsent(result, 1L);
            if (oldValue != null) {
                done = histogram.replace(result, oldValue, oldValue + 1);
            } else {
                done = true;
            }
        }

        return result;
    }

    public long getInterval() {
        long result = 0;

        final long startTime = m_interval;
        final long endTime;

        if (isStopWatchRunning()) {
            endTime = m_interval = currentTime();
        } else {
            endTime = m_end;
        }

        result = convertNanoToMilliseconds(endTime - startTime);

        return result;
    }

    public void stop() {
        if (isStopWatchRunning()) {
            m_end = currentTime();
        }
    }

    private long currentTime() {
        return System.nanoTime();
    }

    private boolean isStopWatchRunning() {
        return (m_end <= 0);
    }

    private long convertNanoToMilliseconds(final long nanoseconds) {
        return nanoseconds / 1000000L;
    }
}

例如,这是我将使用上面的计时器类来衡量多线程应用程序中特定代码的性能的方式:

StopWatch timer = StopWatch.getInstance();
//... some code here to measure
timer.getDuration();

现在我的问题是,如果你看一下getDuration方法,我也会在我的地图中填充一些信息,比如花了x毫秒的调用次数,这样我以后可以使用该地图进行进一步的分析,比如计算平均值、中位数、第95百分位和第99百分位。我下面的代码是线程安全的还是存在任何竞争条件?

boolean done = false;
while (!done) {
    Long oldValue = histogram.putIfAbsent(result, 1L);
    if (oldValue != null) {
        done = histogram.replace(result, oldValue, oldValue + 1);
    } else {
        done = true;
    }
}

调用长oldValue=直方图之间。putIfAbsent(结果,1L) 和<代码>完成=直方图。替换(结果,oldValue,oldValue 1) ,映射中的值可能已更改。因此,oldValue可能过时?


共有1个答案

邓深
2023-03-14

你喊出的部分看起来正确。是的,有时oldValue会过时,但这就是为什么要循环。正当

另一种方法是将原子放入地图中。然后放入/获取原子长,并将其递增。

histogram.putIfAbsent(result, new AtomicLong());
histogram.get(result).incrementAndGet();

在java 8中,您可以使用compute和friends来发挥自己的优势(测试一下,看看您最喜欢哪一个):

histogram.computeIfAbsent(result, AtomicLong::new);
histogram.get(result).incrementAndGet();

// or
if (histogram.putIfAbsent(result, new AtomicLong(1)) == null)
   histogram.get(result).incrementAndGet();

// or even
histogram.compute(result, ($, current) -> {
   if (current == null) return new AtomicLong(1);
   current.incrementAndGet();
   return current;
});
 类似资料:
  • 我遇到了这段代码,它使用Java流,特别是parallelStream(),以便从oracle数据库收集一些数据。见下文,在这种情况下: 范围=一些输入Id列表 据我所知,这是如何工作的: 将范围拆分为1000个块以输入函数 处理线程中的每个块以返回一些结果 将结果汇总到POJO列表中 我的问题是试图减少到单个列表中所带来的潜在竞争条件。这些线程中的许多是否有可能尝试将内容添加到结果列表中并可能损

  • 9.1. 竞争条件 在一个线性(就是说只有一个goroutine的)的程序中,程序的执行顺序只由程序的逻辑来决定。例如,我们有一段语句序列,第一个在第二个之前(废话),以此类推。在有两个或更多goroutine的程序中,每一个goroutine内的语句也是按照既定的顺序去执行的,但是一般情况下我们没法去知道分别位于两个goroutine的事件x和y的执行顺序,x是在y之前还是之后还是同时发生是没法

  • 我们正在对网络套接字使用阻塞系统I/O调用。我们想要的行为是当对套接字调用时,阻塞调用需要返回并抛出一个异常(引用), 看看OpenJDK,这就是它的实现方式。它使用用户信号唤醒阻塞线程。相应的信号处理程序是no-op。在阻塞调用之前,它注册可能被阻塞的线程。当关闭文件描述符时,关闭线程向阻塞的I/O线程发送信号,这导致阻塞调用返回。 不过,我还是认为下面的代码块源代码中存在一个潜在的竞争条件:

  • 问题内容: 我有几个工作人员,每个工作人员都拥有与PostgreSQL的连接。工人用不同的桌子操纵。 工作人员处理来自系统外部的并行请求。被访问的表之一是用户表。当收到一些信息时,我首先需要确保表中有该用户的记录。如果没有记录,我希望首先创建一个。 我正在使用以下成语: 的代码是: 然后测试是否返回任何行。 的(简化)代码为: 当我的系统处理与 同一 用户有关 的 不同信息的并行流时,我经常会收到

  • 9.6. 竞争条件检测 即使我们小心到不能再小心,但在并发程序中犯错还是太容易了。幸运的是,Go的runtime和工具链为我们装备了一个复杂但好用的动态分析工具,竞争检查器(the race detector)。 只要在go build,go run或者go test命令后面加上-race的flag,就会使编译器创建一个你的应用的“修改”版或者一个附带了能够记录所有运行期对共享变量访问工具的tes

  • 问题内容: 如何停止MySQL中的竞争条件?当前的问题是由一个简单的算法引起的: 从表中选择一行 如果不存在,将其插入 然后会得到重复的行,或者如果您通过唯一/主键阻止它,则会出现错误。 现在,通常我认为事务在这里有所帮助,但是由于该行不存在,所以事务实际上并没有帮助(或者我是否错过了什么?)。 LOCK TABLE听起来有些矫kill过正,尤其是如果该表每秒更新多次。 我唯一想到的其他解决方案是