【问题标题】:Performance of synchronization同步性能
【发布时间】:2015-05-11 07:18:45
【问题描述】:

这与我之前的问题类似,因为我仍然不清楚同步关键字。

这次我会很短。

private int count = 0;

synchronized void increment() {
    count++;
}

count 是一个实例变量,在 2 个线程之间共享。

如果线程 t1 和 t2 尝试增加计数并且操作系统给了 t1 机会首先增加计数:-

t1 获取锁并以原子方式递增 count,递增 count 所需的时间为 1 分钟(考虑),包括获取锁所需的时间。

但是线程t2呢,它必须等到锁被释放。 释放锁后,t2 现在自动增加计数,这也需要 1 分钟。

所以同步提供了正确性,但也需要时间来执行。线程意味着在更短的时间内完成工作,那么为什么要在线程中使用同步有什么用呢。

我的理解正确吗?

【问题讨论】:

  • 您已修复原子性但不可见性 count 应为 volatile
  • 这就像你可以使用更多的人在更短的时间内完成一些工作,但是在给定的时间只有一个人可以完成的任务很少(读取关键部分的同步修复)。
  • @NitinDandriyal 您可能正在考虑其他语言。根据 JVM 规范,一个线程中与另一个线程具有发生前发生关系的操作在另一个线程中是可见的。并且在同一监视器上进行同步会创建这种先发生的关系。也可以访问相同的 volatile 变量。
  • @ErwinBolwidt 感谢您的纠正,确实,在特定对象监视器上进入和退出synchronized 时,进入/退出线程还会将所有变量的副本与主内存同步。我在建议时想到了多个 CPU 线程执行单元,我收回了
  • @NitinDandriyal 理想情况下,count 应该是AtomicInteger

标签: java multithreading thread-synchronization


【解决方案1】:

是的,使用同步会降低性能。这里的并发是为了保证共享变量读写的完整性。在您的情况下,如果没有同步,t1 和 t2 可能会读取具有相同值的计数(例如 1),因此当两个线程退出时,计数的值为 2,即使您应该期望它为 3(因为它增加了两次)

【讨论】:

    【解决方案2】:

    并非每个线程都必须执行同步作业(否则我们将失去使用线程的意义)。

    一个高效的场景是线程执行独立的工作(例如,在一个线程上绘制图形元素,同时在另一个线程上播放背景音乐)

    【讨论】:

      【解决方案3】:

      如果不正确,快速的程序将毫无用处。

      假设您的班级是处理您帐户存款的班级。

      假设您的三个客户要求银行将 1000 美元存入您的帐户。假设银行不同步存款操作。

      由于未同步,您可能会遇到竞争情况:

      • 三个客户同时读取您帐户的当前余额:0
      • 所有三个客户都增加它:因此帐户余额变为 1000 美元

      结果:您的帐户中没有 3000 美元,而只有 1000 美元。但这比同步快了 2 毫秒。

      您更喜欢这种情况,还是希望该操作多花 2 毫秒,但您的帐户上有 3000 美元?

      【讨论】:

      • 我希望该操作多花 2 毫秒,并在我的帐户中有 3000 美元。
      • @JBNizet 我不介意别人在我的账户中转入 6000 美元而不是 3000 美元 :)
      【解决方案4】:

      要添加到@Bathsheba 的答案,在多个线程共享和访问同一资源的情况下,不是原子变量,您需要确保只有一个线程在一个给定的时间。考虑将上面的示例修改为以下内容:

      private int count = 0;
      
      synchronized void increment() {
          count = count + 1;
      }
      

      如果您创建increment() 方法synchronized,那么您将面临count 变量状态不一致的风险。具体来说,您的两个线程可以交错(意味着它们同时都在运行)并且一个线程的增量操作可能会被另一个线程覆盖。

      阅读此处了解有关同步的更多信息:https://docs.oracle.com/javase/tutorial/essential/concurrency/interfere.html

      【讨论】:

        猜你喜欢
        • 2018-10-28
        • 1970-01-01
        • 2016-04-09
        • 1970-01-01
        • 2010-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多