并发:一次只有一个用户在编辑一个项目



我研究如何解决这个问题已经有一段时间了,但似乎找不到合适的解决方案。

问题是:

我有一个Java EE应用程序,许多用户可以登录,他们会看到一个项目列表,他们可以选择和编辑其中的任何一个。

所有用户都看到相同的项目列表。如前所述,他们可以编辑项目,但我想将编辑功能限制为一个用户。也就是说,许多用户可以同时编辑不同的项目,但只有一个用户可以编辑特定的项目。

当一个用户正在编辑一个项目时,任何其他试图编辑该项目的用户都应该看到一条消息。

我通过将项inUse上的标志设置为true,然后进行检查来实现这一点。当用户通过单击"保存"或"取消"完成项目编辑后,该标志将设置为false。这种方法的问题是要考虑用户打开浏览器或关闭浏览器的情况。

我尝试设置会话超时,但似乎无法实现,因为当会话超时时,我无法访问该项。我只能访问httprequest会话id。

也许这是一种错误的方法,因为这似乎是许多应用程序都会遇到的问题,而且应该存在一个不那么黑客的解决方案。

我研究过使用线程和同步方法,但不知道这将如何工作,因为一旦用户进入编辑项屏幕,该方法就会退出并释放锁。

我发现了这个解决方案,一次只允许一个用户编辑内容,但不确定这是否是Java中的做法。

有没有更优雅的/java解决方案?如果是的话,你能告诉我正确的方向吗?你将如何实现这一点?

谢谢!

解决方案:尽管最初我认为乐观的锁定是可行的,但我很快意识到这对我的环境并不适用。我决定采用悲观锁定的组合(http://www.agiledata.org/essays/concurrencyControl.html#PessimisticLocking)和超时。

当访问一个项目时,我将inUse字段设置为true,并将对象上次访问的字段设置为当前时间。

每次有人试图编辑对象时,我都会检查inUse字段和lastAccessed字段+5分钟。所以基本上,我给5分钟的时间来编辑用户。

就像在数据库中一样,在数据库中使用时间戳。时间戳与记录一起保存,当一个人提交他的编辑时,除非时间戳相同,否则编辑不会进行(这意味着"自我阅读此记录以来,没有发生任何编辑")。然后,当编辑完成时,将创建一个新的时间戳。

首先,在持久层中,您确实应该使用版本/时间戳字段执行乐观锁定

在UI级别,为了处理您的用例,我会进行资源租赁:

  1. 在表中添加两个字段:

    • LAST_LEASE_TIME:上次租赁时间
    • LAST_LEASE_USER:上次租用记录的用户
  2. 当用户尝试编辑您的记录时,首先检查该记录是否未出租,或者租约是否已过期(即租约没有超过指定的租约时间),或者该用户是否是被授予租约的用户。

  3. 通过您的网络浏览器,定期续订租约,例如使用AJAX调用。

  4. 当用户结束编辑记录时,明确地使租约过期。

通过租赁,你解决了"关闭浏览器"的问题:在租赁期到期而没有进行任何租赁翻新后,算法会自动"释放"资源。

听起来你可以使用:会话Bean报价:

一般来说,如果以下情况成立,您应该使用会话bean:

在任何给定的时间,只有一个客户端可以访问bean实例。bean的状态不是持久的,只存在很短的一段时间(可能只有几个小时)。

MartinFowler描述了这样一个问题的4种模式:

  1. 在线乐观锁定
  2. 在线悲观锁定
  3. 离线乐观锁定
  4. 离线悲观锁定

你应该根据你的问题决定使用哪一个。JPA、JDO和Hibernate提供了开箱即用的1和2。Hibernate也可以处理3(我不确定JPA和JDO)。没有人能处理开箱即用的4个问题,你应该自己执行。

相关内容

最新更新