如何通过访问某些公共数据来同步多个线程

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

我有三个不同的线程,它们创建三个不同的对象来读取/操作一些所有线程共有的数据。现在,我需要确保我们一次只允许访问一个线程。

该示例如下所示。

public interface CommonData {
   public void addData(); // adds data to the cache
   public void getDataAccessKey(); // Key that will be common across different threads for each data type
}

/*
* Singleton class
*/
public class CommonDataCache() {
   private final Map dataMap = new HashMap(); // this takes keys and values as custom objects
}

接口的实现类如下:>

class CommonDataImpl implements CommonData {
    private String key;
    public CommonDataImpl1(String key) {
       this.key = key;
    }

    public void addData() {
      // access the singleton cache class and add
    }

    public void getDataAccessKey() {
      return key;
    }
}

每个线程将如下调用:

CommonData data = new CommonDataImpl("Key1");
new Thread(() -> data.addData()).start();

CommonData data1 = new CommonDataImpl("Key1");
new Thread(() -> data1.addData()).start();

CommonData data2 = new CommonDataImpl("Key1");
new Thread(() -> data2.addData()).start();

现在,当且仅当数据对象的键(传递给线程)相同时,我才需要同步那些线程。

到目前为止,我的思考过程:

我试图让一个类为给定的键提供动态锁定,看起来像这样。

/*
* Singleton class
*/
public class DataAccessKeyToLockProvider {
    private volatile Map<String, ReentrantLock> accessKeyToLockHolder = new ConcurrentHashMap<>();

    private DataAccessKeyToLockProvider() {
    }

    public ReentrantLock getLock(String key) {
        return accessKeyToLockHolder.putIfAbsent(key, new ReentrantLock());
    }

    public void removeLock(BSSKey key) {
        ReentrantLock removedLock = accessKeyToLockHolder.remove(key);
    }
}

因此,每个线程将调用该类并获取锁,并在处理完成后将其删除。但这可能会导致第二个线程可能获取第一个线程插入的锁对象并等待第一个线程释放锁的情况。一旦第一个线程删除了锁,现在第三个线程将完全获得不同的锁,因此第二个线程和第三个线程不再同步。

类似这样的东西:

   new Thread(() -> {
       ReentrantLock lock = DataAccessKeyToLockProvider.get(data.getDataAccessKey());
       lock.lock();
       data.addData();
       lock.unlock();
       DataAccessKeyToLockProvider.remove(data.getDataAccessKey());
    ).start();

如果需要其他详细信息来帮助我解决问题,请告诉我

P.S:从锁提供者中删除密钥是强制性的,因为我将要处理数百万个密钥(不一定是字符串),所以我不希望锁提供者吞噬我的内存

启发了@rzwitserloot提供的解决方案,我试图放置一些通用代码,该代码等待另一个线程完成其处理,然后再访问下一个线程。

public class GenericKeyToLockProvider<K> {
    private volatile Map<K, ReentrantLock> keyToLockHolder = new ConcurrentHashMap<>();

    public synchronized ReentrantLock getLock(K key) {
        ReentrantLock existingLock = keyToLockHolder.get(key);
        try {
            if (existingLock != null && existingLock.isLocked()) {
                existingLock.lock(); // Waits for the thread that acquired the lock previously to release it
            }
            return keyToLockHolder.put(key, new ReentrantLock()); // Override with the new lock
        } finally {
            if (existingLock != null) {
                existingLock.unlock();
            }
        }
    }
}

但是看起来最后一个线程创建的条目不会被删除。无论如何要解决这个问题?

我有三个不同的线程,它们创建三个不同的对象来读取/操作一些所有线程共有的数据。现在,我需要确保我们只授予一个访问权限...

java multithreading java.util.concurrent
1个回答
1
投票

首先,澄清:您任一

© www.soinside.com 2019 - 2024. All rights reserved.