简体   繁体   English

有没有办法在java(或scala)信号量对象中​​包含一个条件来获取方法?

[英]Is there a way to include a Condition to adquire method in java (or scala) Semaphore object?

I have a program that holds many threads, lets put as an example six threads. 我有一个包含许多线程的程序,让我们举例说明六个线程。 Five of them should be able to use concurrently a given resource but the last thread shouldn't if a given condition occurs and should wait until that condition is over. 其中五个应该能够同时使用给定的资源,但是如果给定的条件发生则最后一个线程不应该等到该条件结束。

In my understanding a ReentrantLock can't be used because it can only be held by one thread at a time. 根据我的理解,不能使用ReentrantLock,因为它一次只能由一个线程持有。 In the other hand a Semaphore can be held by many threads at a time but I can't find a way to attach the condition to aquire method. 另一方面,Semaphore可以一次由多个线程持有,但我找不到将条件附加到aquire方法的方法。

Can This high level objects do the trick or I will have to implement this functionality using notify and wait directly? 这个高级对象可以做到这一点,或者我将不得不使用notify直接执行此功能吗?

Eg. 例如。

class A{
   getResource{ ... }
}

//This Runable could be spawn many times at the same time
class B implements Runnable{
   run {
      setConditionToTrue
      getResource
      ...
      getResource
      ...
      getResource
      setConditionToFalse
   }
}

//This will be working forever but only one Thread
class C implements Runnable{
   run{
      loop{
         if(Condition == true) wait
         getResource
      }
   }
}

Thanks in advance pals 在此先感谢好朋友

I am restating your problem here: You want your B threads to access the shared resource concurrently, but your C thread should wait for some condition to occur before using the resource. 我在这里重述您的问题:您希望B线程同时访问共享资源,但您的C线程应该在使用资源之前等待某些条件发生。

If I understand your question correctly, You can use ReentrantLock to solve your problem. 如果我正确理解您的问题,您可以使用ReentrantLock来解决您的问题。

Introduce a new function called getAccess() and make the C thread call this function to get the shared resource. 引入一个名为getAccess()的新函数,并使C线程调用此函数来获取共享资源。 Introduce two more functions to allow and stop the access to shared resource. 引入另外两个函数来允许和停止对共享资源的访问。

class A {

  private final ReentrantLock lock = new ReentrantLock();
  private Condition someCondition = lock.newCondition();
  private boolean bCondition = false;

  getResource{ ... } // Your existing method used by B threads

  getAccess() { // Protected access to some resource, called by C thread
    lock.acquire();

    try {
      if (!bCondition)
        someCondition.await(); // B thread will wait here but releases the lock
    } finally {
      lock.release();
    }
  }

  allowAccess() { // B thread can call this func to notify C and allow access
    lock.acquire();
    try {
      bCondition = true;
      someCondition.signal(); // Decided to release the resource
    } finally {
      lock.release();
    }
  }

  stopAccess() { // B thread can stop the access
    lock.acquire();
    try {
      bCondition = false;
    } finally {
      lock.release();
    }
  }

}

If you want several threads to share a resource, you need to be more specific about the meaning of that sharing. 如果您希望多个线程共享资源,则需要更具体地说明该共享的含义。 Normally this means differentiating between those threads that read the current value of the resource and other threads that change the value. 通常,这意味着区分读取资源当前值的线程和更改值的其他线程。 This implies is a concurrent-read / exclusive-write pattern ('crew') if the writes are to be race-free and stable. 这意味着如果写入是无竞争且稳定的,则是并发读取/独占写入模式(“工作人员”)。

In the Java API, this is provided by the ReentrantReadWriteLock . 在Java API中,这是由ReentrantReadWriteLock提供的。 There are also other alternatives worthy of consideration, such as the carefully-implemented Crew in JCSP. 还有其他值得考虑的替代方案,例如在JCSP中精心实施的船员

Using [J]CSP, a different pattern is also available: that of wrapping the common resource in its own thread and providing access to it via a shared JCSP channel from all the client threads. 使用[J] CSP,还可以使用不同的模式:将公共资源包装在自己的线程中,并通过来自所有客户端线程的共享JCSP通道提供对它的访问。 This client-server pattern is easy to understand and implement, and has the added benefit that it is formally deadlock-free, given that the thread communication graph is acyclic ( more ). 这种客户端 - 服务器模式易于理解和实现,并且具有额外的好处,即它是正式无死锁的,因为线程通信图是非循环的( 更多 )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM