Java信号灯-无需事先发布即可授予许可

时间:2018-08-01 00:02:24

标签: java concurrency quartz-scheduler semaphore deltaspike

我之所以写这个问题,是因为我们在一个qa环境中遇到了一种情况,即信号量似乎失败了。 我们只有一个信号量:

private Semaphore lock = new Semaphore(1);

碰巧一个线程(Quartz作业)正在运行并持有所获取的锁,然后又触发了另一个作业并使其进入执行中间。

这两个作业都需要获取并释放锁,因此,如果第一个作业被延迟,则后者必须等待第一个作业释放锁。

奇怪的是,后者没有等待,它只是通过了lock.acquire()

场景完全不复杂,并且代码从一开始就一直在起作用。到目前为止,我们还无法重新创建它。可能是小故障?

我想知道是否有人知道Quartz和Java信号量之间是否存在某种已知的不兼容性,或者在某些情况下Java信号量是否会失败

编辑 还有一个细节,它是一个基于Deltaspike CDI框架构建的应用程序

这是用于处理锁的Singleton:

import java.util.concurrent.Semaphore;

public class Lock {

  private Lock() {}

  private static class SingletonHolder {
    public static final Lock INSTANCE = new Lock();
  }

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

  /**
  * we allow only one thread at at time
  */
  private Semaphore lock = new Semaphore(1);

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

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

这是第一份工作:

@Scheduled(cronExpression = "{cronExp1}")
public class Job1 implements Job {

  @Override
  public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {  

    method1();

  }

  public void method1(){
    long threadId = Thread.currentThread().getId();

    try{
      logger.debug("Thread # " + threadId + "Requesting lock...");
      Lock.getInstance().getLock();
      logger.debug("Thread # " + threadId + "Lock acquired.");  

      //...some logic

    }catch (PersistenceException e) {
      //.. handling exception
    }catch (Exception e) {      
      //.. handling exception
    }finally {
      Lock.getInstance().releaseLock();
      logger.debug("Thread # " + threadId + "Lock released.");
    }
  }
}

这是第二项工作:

@Scheduled(cronExpression = "{cronExp2}")
public class Job2 implements Job {

  @Override
  public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

    long threadId = Thread.currentThread().getId();
    try{       
      logger.debug("Thread # " + threadId + "Requesting lock...");
      Lock.getInstance().getLock();
      logger.debug("Thread # " + threadId + "Lock acquired.");

      //...some logic

    }catch (PersistenceException e) {
      //.. handling exception
    }catch (Exception e) {      
      //.. handling exception
    }finally {
      Lock.getInstance().releaseLock();
      logger.debug("Thread # " + threadId + "Lock released.");
    }
  }
}

如您所见,作业之间的唯一区别(逻辑除外)是,作业1进入method1内部的关键区域,而Job2进入execute方法内部。

0 个答案:

没有答案