【问题标题】:Concurrency: How to prevent two methods in two different classes to run at the same time?并发:如何防止两个不同类中的两个方法同时运行?
【发布时间】:2018-12-10 00:07:55
【问题描述】:

我有一个用例,我必须防止两个不同类中的两个不同方法同时运行,即如果 A 类有方法 X 而 B 类有方法 Y,我必须确保当方法 X 被执行,我不应该让方法 Y 执行或阻止执行,直到方法 X 完成。

class A{
    @Scheduled
    methodX(){
    }
}

class B{
    methodY(){}
}

一点背景, 这里methodX是一个调度进程,负责从远程数据库读取数据,转换,做一些映射并存储在本地数据库中。

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

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

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

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

            sharedSemaphore.release();
        }
    }
}

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

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

【问题讨论】:

  • 你知道同步关键字吗?
  • 一个 ReentrantLock 而不是一个信号量就足够了。 synchronized 块也可以做到这一点。您只需要一个在两种方法中都可用的对象,可以在其上同步执行。

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    如果您可以从 MethodX 和 MethodY 中提取公共代码,那么您可以简单地摆脱同步。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多