代码之家  ›  专栏  ›  技术社区  ›  Sai Upadhyayula

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

  •  0
  • Sai Upadhyayula  · 技术社区  · 7 年前

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

    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();
         }
        }
    }
    

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

    2 回复  |  直到 7 年前
        1
  •  0
  •   dpatil    7 年前

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

    1. methodX由调度器触发,然后更新表中的一些状态。
    2. methodY由REST API或其他调度器触发,然后它首先检查状态并相应地处理。
        2
  •  0
  •   Biswanath    7 年前

    如果您可以从MethodX和MethodY中提取一个通用代码,那么您就可以轻松地使用Synchronized。

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

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

    推荐文章