簡體   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