如何在没有锁定的情况下同步对象?

时间:2013-06-24 12:59:17

标签: java multithreading synchronization

我见过问题How do determine if an object is locked (synchronized) so not to block in Java?
但我有问题,我无法找到解决方案 在我的Web应用程序中是刷新数据容器的过程,这可能需要很长时间。刷新是在时间间隔内进行的。当然,当一个刷新仍然在容器上工作时,另一个不能(不要破坏容器中的数据) 我想使用后台线程来刷新容器。多个后台工作人员可以同时在多个容器上工作(不同的工作人员用于不同的用户会话,每个用户会话可以在其容器中具有不同的数据)。 当然,我可以在worker中执行synchronize(myContainer)以强制任何其他worker当前没有更新此特定容器。但我宁愿检查是否有工人正在处理容器并退出,如果是的话。另外我想不要更改容器的代码,所以我不想在容器类中添加ReentrantLock并锁定它。
因此,worker具有MyContainer实例,并且想要确定当前是否正在刷新此容器实例。

任何想法如何实现?

3 个答案:

答案 0 :(得分:2)

使用AtomicBoolean,将此代码放入MyContainer类:

AtomicBoolean isRefreshing = new AtomicBoolean(false);

void refresh() {
  if ( isRefreshing.compareAndSet( false, true)) {
    try {
      // refresh
    } finally {
      isRefreshing.set( false);
    }
  }
}

如果你无法触摸MyContainer,可能会创建一个包含AtomicBoolean和MyContainer实例的RefreshWrapper。

答案 1 :(得分:1)

我会将容器放在ConcurrentLinkedQueue中并让工作线程poll成为队列,即

Container container;
while((container = queue.poll()) != null) {
    container.refresh();
}

然后,您有两个选项,具体取决于容器在刷新时是否正在跟踪。

  • 如果是,那么您可以在刷新后立即offer刷新容器重新进入队列。您可以使用if(container.refreshTime < X)防护,以确保您不会在同一时间间隔内刷新容器两次。
  • 如果不是,那么你也可以
    • 使用两个ConcurrentLinkedQueues并在它们之间切换:poll queue1offer queue2上的刷新容器,queue1时清空直到下一个时间间隔,此时poll queue2offer queue1上的刷新容器。
    • 或者,在主线程中保留一个容器数组,当工作线程完成刷新所有容器并进入休眠状态时,offer容器返回队列。

答案 2 :(得分:0)

如果您需要预先检查该对象是否尚未被某个其他线程锁定,则可以使用Thread.holdsLock方法进行此操作。

如果这还不够,请查看advanced lock classes。这些锁提供了丰富的功能集(检查等待锁定,尝试锁定超时,锁定中断等)。他们应该提供足够的功能来解决你的问题。