Java Concurrency控制多个锁

时间:2016-08-22 17:38:42

标签: java concurrency locking semaphore

我有一个关键部分,我需要控制只有那些具有给定属性值的线程能够同时输入。

例如:我有处理产品的线程#1,线程#2处理产品,而线程#3处理服务

现在:

  1. T1首先进入关键部分,以便处理产品

  2. T2想要进入,但由于还有其他产品正在处理中,因此必须等待

  3. T3是最后一个,它可以进入,因为它需要一个服务(不是产品)来处理

  4. T1熄灭,现在T2可以进入

  5. 我觉得它看起来很简单,但我找不到符合要求的东西。 我的问题是,我怎样才能做到这一点?任何有关此信息来源的参考将不胜感激

    非常感谢您提前

3 个答案:

答案 0 :(得分:2)

我认为您无法锁定值类型但尝试此解决方法:将锁定对象放入数组并从ID访问该数组。

类似的东西:

private Object[] locks = new Object[] {new Object(), new Object()};

private void yourMethod(int id)
{
    synchronized(locks[id]) //or id - 1 if you want to stick to your 1 and 2
    {
        //do your things
    }
}

希望有所帮助

答案 1 :(得分:2)

这个怎么样:

private ConcurrentMap<Integer, Semaphore> semaphores = new ConcurrentHashMap<>();

public void enter(int id) {
    Semaphore s = semaphores.computeIfAbsent(id, key -> new Semaphore(1));

    try {
        s.acquire();
        // Critical section.
    } catch (InterruptedException e) {
        // Exception handling.
    } finally {
        s.release();
    }
}
  • 哈希映射可确保快速访问并可动态增长。此外,您还可以将对象用作键。
  • 如果您在编译时知道ID的数量,您还可以使用不可修改或不可变的地图并预先填充它。
  • 信号量也可以调整:为不同的ID设置不同数量的许可和公平保证。
  • 包装类可以提供其他方法,例如非阻塞tryEnter(int)来自Semaphore#tryAcquire()

答案 2 :(得分:1)

我们以不同的方式对此问题进行了排序,并且使用普通锁定会产生高性能影响,而普通锁定在某些情况下会成为瓶颈。但我设法得到了一个解决方案,但未经过测试。这包含一个Lock类,它包含一个Locks池,并根据termId将它们提供给线程。共享相同termId的所有线程将提供相同的Lock。通过这种方式,我们可以获得按termId分组的所有线程,所有线程都排列在不同的队列中。我设置了一个固定的锁池,虽然我认为它也可以是动态的,可以根据需要删除和添加锁。

任何反馈都将不胜感激

import java.util.ArrayList;
import java.util.concurrent.Semaphore;

public class Lock {

  private Lock() {}

  private static class SingletonHolder {

    /** ordered list. Locks with termId null must be at the end **/
    public static final ArrayList<Lock> INSTANCES = new ArrayList<Lock>(){{
      add(new Lock());
      add(new Lock());
      add(new Lock());
      add(new Lock());
      add(new Lock());
      add(new Lock());
      add(new Lock());
    }};

    public static synchronized Lock returnInstance(String termId){
      ArrayList<Lock> sortedList = sortInstances();
      for(Lock instance: sortedList){
        if(termId.equals(instance.getTermId()))
          return instance;
        if(instance.getTermId()==null)
          return instance;
      }

      return null;
    }

    public static ArrayList<Lock> sortInstances(){
      ArrayList<Lock> sortedList=new ArrayList<Lock>();
      for(Lock instance: INSTANCES){
        if(instance.getTermId()==null)
          sortedList.add(instance);
        else
          sortedList.add(0,instance);
      }

      return sortedList;
    }
  }

  /**
  * Use this method to get a reference to a singleton instance of
  * {@link Lock}
  * 
  * @return a singleton instance
  */
  public static Lock getInstance(String termId) {
    return SingletonHolder.returnInstance(termId);
  }

  private Semaphore lock = new Semaphore(1);
  private String termId;

 public void getLock(String termId) throws InterruptedException {
   lock.acquire();
   setTermId(termId);
 }

 public void releaseLock() {   
   lock.release();
   setTermId(null);
 }

  public String getTermId() {
    return termId;
  }

  public void setTermId(String termId) {
    this.termId = termId;
  }
}