【问题标题】:Implementing a Mutex in Java在 Java 中实现互斥锁
【发布时间】:2012-01-08 14:29:24
【问题描述】:

我有一个多线程应用程序(确切地说是 Tomcat 中的一个网络应用程序)。其中有一个类,几乎每个线程都有自己的实例。在该类中,一个方法中有一段代码,一次只有一个线程(用户)可以执行。我的研究使我相信我在这里需要的是一个互斥体(它似乎是一个计数为 1 的信号量)。

所以,经过一番研究,我认为我应该做的是以下几点。重要的是要注意我的锁对象是静态的。

我做得对吗?

public Class MyClass {
  private static Object lock = new Object();
  public void myMethod() {
    // Stuff that multiple threads can execute simultaneously.
    synchronized(MyClass.lock) {
      // Stuff that only one thread may execute at a time.
    }
  }
}

【问题讨论】:

  • 没有理由不应该工作。你也可以使用ReentrantLock 来达到同样的效果。

标签: java multithreading mutex


【解决方案1】:

在您的代码中,myMethod 可以在任何线程中执行,但一次只能在一个线程中执行。这意味着永远不可能有两个线程同时执行此方法。我认为这就是你想要的 - 所以:是的。

【讨论】:

  • 谢谢!线程会“排队”等待获得锁吗?拿不到锁就不会马上失败?
  • 是的,他们会等的。如果方法永远不会返回,他们甚至可能会无限挂起并冻结应用程序。
  • 为避免挂起,您可能需要查看 Futures 模式/框架,或者有某种形式的回调系统。这将允许那些等待的人“在等待时拿票并做其他事情”。
  • @brainzzy 根据 JVm 实现,这些被阻塞的线程是使用睡眠锁还是自旋锁(忙等待)阻塞的?
【解决方案2】:

通常,多线程问题来自可变性 - 其中两个或多个线程正在访问相同的数据结构,并且其中一个或多个对其进行修改。

第一个直觉是使用锁定来控制访问顺序,正如您所建议的那样 - 但是您可能会很快遇到锁定争用,因为您的线程停在锁定监视器上,您的应用程序会失去大量处理时间来进行上下文切换。

您可以通过迁移到不可变数据结构来解决大部分问题 - 因此您可以从设置器返回一个新对象,而不是修改现有对象,以及利用并发集合,例如 ConcurrentHashMap / CopyOnWriteArrayList。

并发编程是您需要了解的东西,尤其是在当今现代计算世界中吞吐量来自并行化的情况下。

【讨论】:

  • 谢谢。在这种情况下,我保护的不是数据,而是对一次只允许一个“用户”的外部硬件资源的访问。我同意,并发编程是必不可少的,我计划在那里提高我的技能。
  • 有效点 - 尽管我仍然对这种瓶颈可能对系统产生的影响持谨慎态度。不过,我大部分时间都在调整高负载/吞吐量应用程序
【解决方案3】:

这将允许一个线程一次通过该块。其他线程会等待,但没有队列,不能保证线程会以公平的方式获得锁。事实上,使用偏向锁,它不太可能是公平的。 ;)

你的锁应该是final 如果有任何原因它不能它可能是一个错误。顺便说一句:您也许可以改用synchronized(MyClass.class)

【讨论】:

  • MyClass.class 可用于其他类,因此可能是错误来源。
  • 谢谢。在这种情况下,我可以接受不公平。该应用程序的使用非常简单,而且他们是一个被俘虏的观众(即没有其他应用程序可以与我竞争)。
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 2011-07-20
  • 2011-06-23
  • 1970-01-01
  • 2010-12-01
  • 2014-12-31
  • 2020-05-29
  • 2018-05-23
相关资源
最近更新 更多