繁体   English   中英

Java Concurrency控制多个锁

[英]Java Concurrency control multiple locks

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

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

现在:

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

  2. T2想要进入,但由于还有另一种产品正在处理,它必须等待

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

  4. T1熄灭,现在T2能够进入

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

非常感谢你提前

我认为您无法锁定值类型但尝试此解决方法:将锁定对象放入数组并从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
    }
}

希望能帮助到你

这个怎么样:

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设置不同数量的许可和公平保证。
  • 包装类可以通过Semaphore#tryAcquire()提供其他方法,例如非阻塞tryEnter(int) Semaphore#tryAcquire()

如果你真的需要这个逻辑,它可以这样实现:

private final Lock lock = new Lock();

public void process() {
    boolean locked = false;
    if (isProduct()) {   // Depends on the current thread
        lock.lock();
        locked = true;
    }

    try {
        // Do the work here
    } finally {
        if (locked) {
            lock.unlock();
        }
    }
}

但问题本身就是一个糟糕的设计。 只需创建方法processProduct()processService() ,使第一个synchronized并从您的线程中调用您真正需要的那个。

我们以不同的方式对此问题进行了排序,并且使用普通锁定会产生高性能影响,这在某些情况下会成为瓶颈。 但我设法得到了一个解决方案,但未经过测试。 这包含一个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;
  }
} 

暂无
暂无

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

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