繁体   English   中英

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

[英]How synchronize on object without locking?

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

任何想法如何实现?

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

AtomicBoolean isRefreshing = new AtomicBoolean(false);

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

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

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

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

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

  • 如果它们是,那么您可以在刷新后立即将刷新的容器offer回队列。 您可以使用if(container.refreshTime < X)防护来确保不在同一时间间隔内刷新容器两次。
  • 如果他们不是那么你也可以
    • 使用两个ConcurrentLinkedQueues和替代它们之间: pollqueue1offer的刷新容器queue2 ,并且当queue1是空的睡眠,直到下一个时间间隔,在该点pollqueue2offer在刷新容器queue1
    • 或者,在主线程中保留一个容器数组,并在工作线程完成刷新所有容器并进入休眠状态时将容器offer回队列。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM