Java信号量-未经事先发布而授予的许可

Java信号量-未经事先发布而授予的许可,java,concurrency,quartz-scheduler,semaphore,deltaspike,Java,Concurrency,Quartz Scheduler,Semaphore,Deltaspike,我写这个问题是因为我们在一个qa环境中遇到了一个场景,在这个场景中,信号量似乎失败了。 我们只有一个信号灯: 专用信号量锁=新信号量(1); 一个线程(石英作业)正在运行,持有所获取的锁,然后触发另一个任务,并在执行过程中执行。 两个作业都获取并释放锁,因此如果第一个作业被延迟,后者必须等待第一个作业释放锁 奇怪的是后者没有等待,它只是通过了锁。acquire() 场景一点也不复杂,代码从一开始就可以工作。到目前为止我们还没能重现它,我不知道。可能是故障 我想知道是否有人知道Quartz和Ja

我写这个问题是因为我们在一个qa环境中遇到了一个场景,在这个场景中,信号量似乎失败了。 我们只有一个信号灯:

专用信号量锁=新信号量(1);

一个线程(石英作业)正在运行,持有所获取的锁,然后触发另一个任务,并在执行过程中执行。 两个作业都获取并释放锁,因此如果第一个作业被延迟,后者必须等待第一个作业释放锁

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

场景一点也不复杂,代码从一开始就可以工作。到目前为止我们还没能重现它,我不知道。可能是故障

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

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

这是处理锁的单例:

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进入方法1内的关键区域,而作业2进入执行方法内的关键区域。您能否分享一个最小且可验证的示例,说明所述的
锁如何在您的代码中使用?谢谢@MickMnemonic,我刚刚用代码信息更新了这个问题,您如何知道两个线程能够同时获得许可?我注意到您的
finally
块在释放许可证之前不会打印消息。因此,从理论上讲,第二个线程在第一个线程发布许可证之后,但在第一个线程打印其消息之前,打印“Lock acquired”消息是可能的。捕捉得好,但我从每个作业的逻辑部分的日志中知道。我有很多来自Job2的日志条目和来自Job1的日志条目,这是以前从未发生过的事情。时间间隔为30分钟,第一份工作耗时45分钟。在第31分钟,或多或少,我开始看到两个作业的混合日志。除此之外,由于它们都与数据库交互,我看到了其中的不一致性,这是由于重叠造成的。希望它能帮助这些作业在同一个JVM中运行吗?