这种事情已经完成了一百万次,但我确信,但我的搜索foo今天看起来很虚弱,我想获得关于通常被认为是最佳实现这一目标的方法。锁定线程间并发数据库记录
我的应用程序会跟踪系统中在线用户的会话。每个会话对应于数据库中的单个记录。会话可以通过以下两种方式之一结束。收到“停止”消息,或会话可能超时。前一种情况很简单,它在消息处理线程中处理,一切都很好。后一种情况是关注点来自哪里。
为了处理超时,每条记录都有一个结束时间列,每次收到该会话的消息时都会更新一次。为了使超时工作,我有一个线程返回NOW()(结束时间为过去)的数据库中的所有记录,并通过处理关闭这些会话。这里的问题是,当超时线程正在处理同一会话时,可能会收到会话消息。我最终在超时线程和消息处理线程之间进行竞争。
我可以使用一个信号灯或类似的东西,只是防止消息线程在超时发生时处理,因为它只需要每30秒或一分钟运行一次。但是,随着用户表变大,这将会遇到一些严重的性能问题。我想我想知道的方法是在消息线程中知道此记录目前正在由超时线程处理。如果我能够实现这一点,我可以放弃该消息或等待超时线程结束,但仅在冲突现在而不是总是冲突的情况下。
目前我的应用程序直接使用JDBC。如果我使用Hibernate这样的框架,会不会有更简单/标准的方法来解决这个问题?
您可以通过会话ID而不是线程级别来包装信号量,因此您已在消息处理程序和超时线程的关闭部分中同步(sessionID)块。我认为它不像你想要的那么干净,但是它比将整个线程锁定在单个信号量上的性能影响更小,因为只有该会话的消息才会被阻塞。 – Thomas 2012-02-06 16:24:18
这将如何工作?我的理解是,这将锁定* object * sessionID,而不是sessionID的*值*。由于在数据库读取之后在两个线程中创建的对象不是同一个对象,所以它看起来好像永远不会阻塞。如果您有一个锁对象的字段并在同步块之前从两个线程更新它,则您拥有与之前的并发性相同的问题,只需将焦点切换到锁对象即可。除非有一种方法可以同步我不知道的*值*上的块。 – tdimmig 2012-02-06 21:51:13
答案根据你的结构而改变。如果你有mysession.handleMessage(x)和mysession.closeAndCleanup(),你应该可以锁定mysession。然后竞争条件是,如果在会话被标记为关闭之后但在到达同步块之前接收到消息,则将处理消息并关闭会话或关闭会话,并且消息将返回关于超时的错误。如果结构是handlemessage(ID,msg)和close(ID),其中ID只是一个int,那么您需要一个Map或其他东西来同步。 – Thomas 2012-02-07 15:53:12