【问题标题】:Performance of Java synchronized, semaphore, and queueJava 同步、信号量和队列的性能
【发布时间】:2020-09-11 01:31:41
【问题描述】:

我正在编写一小段代码,它将被多个线程同时调用以收集有关进程的统计信息。代码简短而快速,但必须以某种方式同步以保持统计数据正确。典型负载约为每秒 100-200 个调用,但在一天中的某个时间点可能会升级到每秒 5000 个调用。

  1. synchronized 处理这个速度慢吗?如果我有 16 个内核而不是 4 个内核,那么处理我拥有的更多内核是否会变得更昂贵?

     // This method is called by multiple threads
     public synchronized void record(String alias, long result, int delta) {
       // compute custom stats here... (short & quick)
     }
    
  2. 我正在考虑的另一个选项是使用Semaphore 来访问临界区。它们比选项#1 快吗?他们还在幕后使用锁吗?

     private Semaphore s = new Semaphore(1);
    
     public void record(String alias, long result, int delta) 
         throws InterruptedException {
       boolean acquired = false;
       try {
         this.s.acquire();
         acquired = true;
         // compute custom stats here... (short & quick)
       } finally {
         if (acquired) this.s.release();
       }
     }
    
  3. 最后,我正在考虑一个队列(每个调用者是一个生产者 + 一个 Executor 作为消费者),但我想避免一个额外的线程/执行者作为消费者。

  4. 其他更好的选择?

最后但同样重要的是,对于我每秒 5000 次调用的用例,我是否过于担心?如果是这样,我会使用最简单的选项(同步方法)来控制并发。

【问题讨论】:

  • 不知道你在做什么。没有更好的描述,没有人能够回答。
  • 闻起来像 Micrometer 之类的东西可能已经解决了。如果没有,通常的方法是让线程将它们的更新发布到异步队列,并有一个单独的更新线程来消费它。
  • @chrylis-cautiouslyoptimistic- 感谢您的回复。我在看千分尺......想知道如何指定我需要为统计数据实现的自定义逻辑。将继续阅读。
  • 我看不出有任何理由超越synchronized。您的第二个示例同时使用了synchronized Semaphore,这没有意义。队列肯定只会让事情变得更糟,因为在添加队列和从中删除队列时都需要同步或信号量。
  • @MarquisofLorne 使用合适的(阻塞)队列将为您解决大部分问题。

标签: java multithreading synchronization critical-section


【解决方案1】:

如果您的计算又短又快,那么使用 semaphore 与 synchronized 并不能真正给您带来领先优势。对于消息的并发处理,生产者/消费者是要走的路。您可以使用阻塞队列,然后旋转多个消费者线程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多