简体   繁体   English

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

[英]How synchronize on object without locking?

I have seen question How do determine if an object is locked (synchronized) so not to block in Java? 我已经看到问题如何确定一个对象是否被锁定(同步),以免在Java中阻塞?
But I have problem on which I can not figure out solution. 但我有问题,我无法找到解决方案。
In my web application is process in which refresh of data container and that can take long time. 在我的Web应用程序中是刷新数据容器的过程,这可能需要很长时间。 Refresh is forced to be made in time intervals. 刷新是在时间间隔内进行的。 Of course when one refresh is still on container working another cannot (to do not corrupt data in container). 当然,当一个刷新仍在容器上工作时,另一个不能(不要破坏容器中的数据)。
I want to use background thread to refresh container. 我想使用后台线程来刷新容器。 Multiple background workers can be working at the same time on multiple containers (different workers for different user sessions, every user session can have different data in their container). 多个后台工作人员可以同时在多个容器上工作(不同的工作人员用于不同的用户会话,每个用户会话可以在其容器中具有不同的数据)。
Of course I can do synchronize(myContainer) in worker to force that any other worker is not currently updating this particular container. 当然,我可以在worker中进行synchronize(myContainer)以强制任何其他worker当前没有更新此特定容器。 But I rather want to check if any worker is working on container and exit, if is. 但我宁愿检查是否有工人正在处理容器并退出,如果是的话。 Also I would like to not change code of container, so I would like not to add ReentrantLock inside container class and lock on that. 另外我想不要更改容器的代码,所以我不想在容器类中添加ReentrantLock并锁定它。
So worker have MyContainer instance and want to determine if any other worker is currently refreshing this container instance. 因此,worker具有MyContainer实例,并且想要确定是否有任何其他worker正在刷新此容器实例。

Any ideas how to achieve that? 任何想法如何实现?

use an AtomicBoolean , put this code in your MyContainer class: 使用AtomicBoolean ,将此代码放在MyContainer类中:

AtomicBoolean isRefreshing = new AtomicBoolean(false);

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

If you can not touch MyContainer, maybe create a RefreshWrapper holding the AtomicBoolean and the MyContainer instance. 如果您无法触摸MyContainer,可能会创建一个包含AtomicBoolean和MyContainer实例的RefreshWrapper。

I would put the containers in a ConcurrentLinkedQueue and have the worker threads poll the queue ie 我会将容器放在ConcurrentLinkedQueue中 ,让工作线程poll队列,即

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

Then you have two options depending on whether the containers are tracking when they are being refreshed. 然后,您有两个选项,具体取决于容器在刷新时是否正在跟踪。

  • If they are then you can offer the refreshed containers back into the queue as soon as they're refreshed. 如果它们是,那么您可以在刷新后立即将刷新的容器offer回队列。 You can use an if(container.refreshTime < X) guard to ensure that you don't refresh the container twice in the same time interval. 您可以使用if(container.refreshTime < X)防护来确保不在同一时间间隔内刷新容器两次。
  • If they are not then you can either 如果他们不是那么你也可以
    • Use two ConcurrentLinkedQueues and alternate between them: poll on queue1 and offer the refreshed container on queue2 , and when queue1 is empty sleep until the next time interval, at which point poll on queue2 and offer the refreshed containers on queue1 . 使用两个ConcurrentLinkedQueues和替代它们之间: pollqueue1offer的刷新容器queue2 ,并且当queue1是空的睡眠,直到下一个时间间隔,在该点pollqueue2offer在刷新容器queue1
    • Or, keep an array of the containers in the main thread, and offer the containers back into the queue when the worker threads have finished refreshing all of the containers and have gone to sleep. 或者,在主线程中保留一个容器数组,并在工作线程完成刷新所有容器并进入休眠状态时将容器offer回队列。

If you need to pre-check if the object has not already been locked by some other thread, this should be possible with Thread.holdsLock method. 如果您需要预先检查对象是否尚未被其他线程锁定,则可以使用Thread.holdsLock方法。

If this is not enough, look into the advanced lock classes . 如果这还不够,请查看高级锁类 These locks provide the rich set of features (check that is waiting on the lock, try to lock with time out, lock interruptably, etc). 这些锁提供了丰富的功能集(检查等待锁定,尝试锁定超时,锁定中断等)。 They should provide enough features to solve your problem. 他们应该提供足够的功能来解决您的问题。

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

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