Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何实施";锁-现有服务结构中的层_Java_Spring_Transactions_Service_Locking - Fatal编程技术网

Java 如何实施";锁-现有服务结构中的层

Java 如何实施";锁-现有服务结构中的层,java,spring,transactions,service,locking,Java,Spring,Transactions,Service,Locking,当前情况:我有一个具有几种典型服务方法的服务,如create()、remove()、findXy()、。。等等。现在我想防止同时进行两个不同的服务调用,这意味着我想在第一次输入servicecall后锁定我的servicecall,因此第二个客户端(或者再次是同一个客户端)只会在第一个客户端完成后才输入该方法 出于锁定目的,我们通常使用ReentrantLocks。它们工作得非常好。但现在我怀疑如何实现这些可重入锁,因为我不想在每个方法中都插入它们。此外,我们的服务层已经自己定义了它们的事务上下

当前情况:我有一个具有几种典型服务方法的服务,如create()、remove()、findXy()、。。等等。现在我想防止同时进行两个不同的服务调用,这意味着我想在第一次输入servicecall后锁定我的servicecall,因此第二个客户端(或者再次是同一个客户端)只会在第一个客户端完成后才输入该方法

出于锁定目的,我们通常使用ReentrantLocks。它们工作得非常好。但现在我怀疑如何实现这些可重入锁,因为我不想在每个方法中都插入它们。此外,我们的服务层已经自己定义了它们的事务上下文,这意味着,当我将它们集成到方法本身中时,一个事务已经在锁发生之前启动了

public class WorkerServiceServerImpl implements WorkerServiceRemote
{
  private static final ReentrantLock workerLock = new ReentrantLock( true );

  @Autowired
  private WorkerDao                 workerDao;

  @Override
  @Transactional
  public int createWorker( int projectId ) throws RemoteException
  {
    workerLock.lock();//NO GOOD! Transaction already started!

    try
    {
      workerDao.create( projectId );

      //Do some more stuff...
    }
    finally
    {
      workerLock.unlock();//Unlock, next request can be handled!
    }
  }

  ...
}
当然,我可以在这个WorkerServiceImpl类上创建一个ServiceLayer,然后将调用转发到原始服务,但是由于我有30个服务,我想知道是否有任何全局解决方案可以解决这个问题。或者是否可以创建自己的注释,在事务启动之前触发

欢迎提出任何意见,提前感谢! 伊梅内


编辑:为了简单起见,我选择CRUD方法。当然,这些服务调用要高级得多,可以在一次调用中调用不同的CRUD方法。

关于此设计,可以提出以下几点:

  • 对服务方法应用锁的需要看起来很奇怪。如果您在并发执行服务方法时遇到一些问题,那么最好在访问底层数据库时通过正确配置事务来解决这些问题

  • unlock()
    必须在
    finally
    块内调用

  • 如果您的服务是单例的,那么使用
    ReentrantLock
    相当于将方法标记为
    synchronized

  • 您可以创建一个方面来将同步应用于您的方法。看,尤其是


    • 因为您似乎在使用Spring,所以可以定义一个单例锁拦截器,并将其放在事务拦截器之前的拦截器堆栈中。这个拦截器非常简单:

      import org.aopalliance.intercept.*;
      public class LockInterceptor implements MethodInterceptor {
      
          @Override
          public synchronized Object invoke(MethodInvocation mi) throws Throwable {
              return mi.proceed();
          }
      }
      

      我很挑剔,但是如果服务不是单例,那么它的实现就不等同于将方法标记为已同步,因为锁是静态的。逐点回答:1)有时在其他服务调用完成之前,某些服务调用不允许发生,这就是为什么我们要锁定它们。2) 当然,在finally块中,为了简单起见,将其忽略,将在示例中更正它。3) 可重入锁还有其他好处,例如,我们可以在一个锁中锁定多个方法,而不仅仅是单个方法。因为我们的服务是单例的,所以可能真的不需要静态的。4) 我会检查这一章,谢谢@ymene:
      synchronized
      也不会锁定单个方法-它相当于
      synchronized(this){…}
      ,因此类的所有
      synchronized
      方法都是互斥的。@axtavt但我不会让所有方法都互斥,而是让它们成为特殊的方法,我想自己声明它们。使用ReentrantLock而不是synchronized有什么缺点吗?@ymene:没有,除了冗长。这种可能性看起来很有趣。我会尽力让它发挥作用并给出回应。我喜欢你的想法,而且效果很好,但ppl认为这太神奇了,所以他们更喜欢独立的服务层。但是谢谢你的回复!