是什么导致了缓冲类中的赛车状况

问题描述 投票:0回答:1

我正在尝试创建一个通用类来进行一些同步缓冲写入操作。

我试图最大限度地减少锁定时间,所以我使用了一个非最终锁定对象,我的想法足以保持类同步并避免竞赛条件...但在测试它时我仍然得到竞赛条件并且最终的结果是一些实体被刷新了多次

任何人都可以尝试向我解释一下是什么导致了赛车状况,什么情况是导致同步问题的原因?

请不要告诉我同步方法flushCache...我知道如何解决这个问题,我只是想了解为什么会发生

public abstract class SynchronizedBufferedSaver<E> {


   private final int MAX_BUFFER_SIZE;

   private Set<E> savingBuffer;

   public SynchronizedBufferedSaver(final int max_buffer_size) {
      MAX_BUFFER_SIZE = max_buffer_size;
      savingBuffer = ConcurrentHashMap.newKeySet((int) (max_buffer_size * 1.5));
   }


   public void save(@NonNull final E entity) {
      copyToCache(entity);
      flushCache(false);
   }

   abstract protected void persist(@NonNull final Set<E> cache);

   public void flushCache(final boolean force) {
      synchronized (savingBuffer) {
         if (!savingBuffer.isEmpty() && (force || savingBuffer.size() >= MAX_BUFFER_SIZE)) {
            final Set<E> tmp = savingBuffer;
            savingBuffer = ConcurrentHashMap.newKeySet((int) (MAX_BUFFER_SIZE * 1.5));
            persist(tmp);
         }
      }
   }

   private void copyToCache(@NonNull final E entity) {
      savingBuffer.add(entity);
   }


}
java synchronization synchronized thread-synchronization
1个回答
0
投票

最终放弃尝试减少同步块,对于一个小任务来说太费力了。

我尝试了

volatile
atomicreference
但没有成功

以下代码将解决额外同步块的问题...尽管如果有人有一篇文章或描述如何使用 1 个同步块实现这一点,请发送给我,我很想学习

软件包 br.com.fisgar.utils;

public abstract class SynchronizedBufferedSaver<E> {


   private final int MAX_BUFFER_SIZE;

   private final Set<E> savingBuffer;

   public SynchronizedBufferedSaver(final int max_buffer_size) {
      MAX_BUFFER_SIZE = max_buffer_size;
      savingBuffer = new HashSet<>((int) (max_buffer_size * 1.5));
   }


   public void save(@NonNull final E entity) {
      copyToCache(entity);
      flushCache(false);
   }

   abstract protected void persist(@NonNull final Set<E> cache);

   public synchronized void flushCache(final boolean force) {
      final Set<E> tmp = new HashSet<>();
      synchronized (savingBuffer) {
         if (!savingBuffer.isEmpty() && (force || savingBuffer.size() >= MAX_BUFFER_SIZE)) {
            tmp.addAll(savingBuffer);
            savingBuffer.clear();
         }
      }
      if (!tmp.isEmpty()) {
         persist(tmp);
      }
   }

   private void copyToCache(@NonNull final E entity) {
      synchronized (savingBuffer) {
         savingBuffer.add(entity);
      }
   }
}
© www.soinside.com 2019 - 2024. All rights reserved.