并发:如何防止两个不同类中的两个方法同时运行?

时间:2018-12-10 00:07:55

标签: java concurrency locking semaphore java.util.concurrent

我有一个用例,其中必须防止两个不同类中的两个不同方法同时运行,即如果A类具有方法X而B类具有方法Y,则必须确保在使用methodX时执行后,在methodX完成之前,我不应该允许方法Y执行或阻止执行。

class A{
    @Scheduled
    methodX(){
    }
}

class B{
    methodY(){}
}

有点背景, methodX是一个计划好的过程,负责从远程数据库读取数据,进行转换,执行一些映射并将其存储在本地数据库中。

methodY是一种通用实现(可以由REST调用或另一个计划的进程触发),它从不同的源读取数据,其中一个源是methodX存储的数据,之后读取它还会进行一些映射,并将数据发送到另一个系统。

由于我必须在两个不同的类中同步两个不同的方法,所以sync关键字或块不是正确的解决方案。

在这里,我在方法X和方法Y中使用了共享计数信号量,即

class A{
    @Scheduled
    methodX(){
        if(sharedSemaphore.tryAcquire()){       
            // read data, do mappings etc.
            ...
            ...

            sharedSemaphore.release();
        }
    }
}

class B{
    methodY(){
     if(sharedSemaphore.tryAcquire()){
         ...
         ...
         ...
         sharedSemaphore.release();
     }
    }
}

上面的代码示例只是实际实现的一小部分,有没有更好的方法呢?信号量在这里使用正确的并发原语吗?如何确保两个不同类中的两个不同方法不能同时执行?

2 个答案:

答案 0 :(得分:0)

如果它是从两个不同的流中发生的,那为什么不能在DB中存储一些状态呢? 例如

  1. methodX由调度程序触发,然后更新表中的某些状态。
  2. 方法REST API或其他调度程序触发,然后首先检查状态并进行相应处理。

答案 1 :(得分:0)

如果您可以从MethodX和MethodY中提取通用代码,则可以轻松进行同步。

尽管,通常,这对于Web服务器和rest api来说不是一个好的解决方案,因为您很可能会在服务器之间横向扩展或平衡负载。

因此可以归结为跨机器序列化代码(通过锁定?)。不确定您的技术堆栈是什么,但是可以使用基于数据库的锁定,mysql get_lock或oracle dbms_lock,一些数据库状态(这几乎是您正在使用自己的锁定机制)或任务队列(如果使用的是消息传递)帧。您也可以使用Akka演员。