预订预订申请中的同步

时间:2015-07-09 08:12:17

标签: java multithreading concurrency dao synchronized

对于经典Servlet的同步,我有一个非常基本的疑问 - >服务 - > DAO模式。

假设我有一个由多个并发用户访问的票务预订应用程序。没有两个用户应该最终预订同一张票。当两个不同的用户尝试访问机票预订时,我认为会发生以下情况 -

  • Web容器为这两者创建请求/响应对象 要求。将请求URL映射到servlet(比如说,BookingServlet)。
  • 为每个请求创建线程以运行服务方法 BookingServlet。
  • 服务 - > doPost方法创建一个BookingService对象并传递席位信息。
  • BookingService对象执行一些业务逻辑并实例化 BookingDAO对象与DB连接并进行更新。

现在,为了避免两个用户预订相同的机票,必须在哪里进行同步?

是在BookingService还是在BookingDAO?

但是,这是我的疑问,对于每个请求,我们实际上创建了一个单独的BookingService和BookingDAO对象 - 这不会破坏将同步放在那里的目的吗?

2 个答案:

答案 0 :(得分:1)

有多种方法可以解决您的问题。

  1. 制作BookingService和/或BookingDAO单身人士。通常不需要有更多实例。然后你可以做同步。或者您可以在课堂上进行同步。例如。 synchronized(BookingService.class)
  2. 仅当您只运行一个应用程序实例时,此方法才有效。因此,我建议使用第二个选项(假设您使用的是关系数据库)

    1. 使用您的数据库执行“同步”。假设您在数据库中的每个座位都有“无保留”的票证,并且您希望能够为用户保留该票证,或者如果订单被取消(或在给定时间内未付款)则撤消此票据。然后您可以使用“乐观”方法进行预留(伪SQL):update ticket set reserved_by = 'CustomerA' where ticket_id = 23 and reserved_by = null更新后,您需要检查更新行的数量。如果是1,那么一切都很好,如果是0,则意味着其他人保留了中间票,客户需要进行新的预订。

答案 1 :(得分:0)

唯一标识符

一个相对简单的解决方案可以使用Java UUID。我们在项目中使用此方法,以确保人们无法同时创建相同的lobby

import java.util.UUID;

public class GenerateUUID {

  public static final void main(String... aArgs){
    //generate random UUIDs
    UUID idOne = UUID.randomUUID();
    UUID idTwo = UUID.randomUUID();
    log("UUID One: " + idOne);
    log("UUID Two: " + idTwo);
  }

  private static void log(Object aObject){
    System.out.println( String.valueOf(aObject) );
  }
} 

此外,如果您希望降低一个用户与另一个用户获得相同UUID的可能性。您可以将用户的Primary Key连接到 UUID 的末尾。

例如067e6162-3b6f-4ae2-a171-2470b63dff00变为067e6162-3b6f-4ae2-a171-2470b63dff00-23,如果每个用户包含不同Primary Key概率,则两个用户点击相同Token的概率非常低。

  
      
  1. 创建唯一的会话ID,例如UUID sessionID = UUID.randomUUID();
  2.   
  3. 开始交易
  4.   
  5. 从DB中删除与请求中的任何令牌匹配的任何令牌,例如
      DELETE FROM Tokens WHERE TokenID = < requested-token>
  6.   
  7. 获取受影响的行数
  8.   
  9. 如果受影响的行数正好为1,则令牌有效。创建一个会话,例如
      插入会话VALUES(sessionUUID,userID,loginTime,...)
  10.   
  11. 提交交易
  12.   

source: finnwjava: race conditions - is there a way to make sure several lines of code will be executed together?

相互排斥

否则我相信,您需要开发一些互相排斥的东西,以便双方(预订机票的人不能同时预订同一张机票)。看Lamport's bakery algorithm

  

Lamport在其入口处设想了一家带有编号机的面包店,因此每个客户都会得到一个唯一的号码。当顾客进入商店时,数字会增加一。全局计数器显示当前正在服务的客户的编号。所有其他客户必须排队等待,直到面包师完成为当前客户提供服务并显示下一个号码。当顾客完成购物并且已经处理了他或她的号码时,店员递增号码,允许下一个顾客被送达。该客户必须从编号机中抽取另一个号码才能再次购物。

例如,使用static LinkedList来跟踪今天订购的每个票号。