Java 大小为1的信号灯是最佳选择?

Java 大小为1的信号灯是最佳选择?,java,multithreading,locking,semaphore,java.util.concurrent,Java,Multithreading,Locking,Semaphore,Java.util.concurrent,如果您有一个资源,一个人一次只能访问一次,那么您可以使用大小为1的信号量,或者您可以只使用一个ReentrantLock实例 使一个或另一个做出更好决定的细微差别是什么?信号灯s有利于计算许可证/释放,因此如果您有多个资源,锁等等。这对你没有多大帮助。但是,如果您只有一个要保护的资源,那么它们就足够了。计算信号量示例:您有一个受保护的对象,限制不超过五个线程可以同时访问它。在这种情况下,初始值为5的计数信号量是数学上合适的。是理解结构的最佳读物之一 有区别: 信号量可以由一个线程获取,然后由另一

如果您有一个资源,一个人一次只能访问一次,那么您可以使用大小为1的信号量,或者您可以只使用一个ReentrantLock实例


使一个或另一个做出更好决定的细微差别是什么?

信号灯
s有利于计算许可证/释放,因此如果您有多个资源,
等等。这对你没有多大帮助。但是,如果您只有一个要保护的资源,那么它们就足够了。

计算信号量示例:您有一个受保护的对象,限制不超过五个线程可以同时访问它。在这种情况下,初始值为5的计数信号量是数学上合适的。是理解结构的最佳读物之一

有区别:

  • 信号量可以由一个线程获取,然后由另一个线程释放。这样,一个线程可以向另一个线程发送信号。计数为1的信号量也可用于互斥。另一方面,锁仅用于互斥
  • 信号量不可重入。这意味着即使许可证已被同一线程获取,但当许可证耗尽时,线程也无法获取信号量。锁可以是可重入的

  • 虽然这确实可以通过
    synchronized
    Semaphore
    实现,但您首先必须弄清楚如何使用此资源。如果使用
    synchronized
    ,这意味着您必须在线程中监视同步:

    public void run() {
      // some code
      synchronized (resource) {
        // use resource
      }
    }
    
    如果您不想让线程监视这一点(我认为这更好),请在资源的getter方法中使用
    Semaphore

    public Resource acquireResource() {
      // acquire semaphore
      return resource;
    }
    
    public void releaseResource() {
      // release semaphore
    }
    
    在线程中,只需执行以下操作:

    public void run() {
      // some code
      Resource resource = ResourceContainer.getResource();
      // do something with resource
      releaseResource();
    }
    

    您可以向这些方法添加
    Object
    参数,只是为了比较同一对象是否释放了信号量。

    为什么不
    synchronized
    ?我认为不会有任何问题-当
    allows
    设置为1时,两个API几乎相同。而且这两种实现都基于
    AbstractQueuedSynchronizer
    ,所以行为和性能也应该接近相同。@Raif H绝对零差异吗?我能想到的唯一一件事是,如果您不能100%确定它将始终是1的限制。正如assylias所说,它们(以及
    java.util.concurrent
    中的许多其他工具)基于
    AbstractQueuedSynchronizer
    ,并且将具有相同的性能特征。选择一个语义正确的。虽然是真的,但我不知道这是如何回答这个问题的。