我有两个数组,我需要跨线程同步对它们的访问。我将把它们放在一个同步块中。问题是,我只能一次性将其中之一传递给“同步”。
如何确保对两个阵列的访问是同步的?我是否将它们放在一个类中并创建一个对象?或者我只在同步块中访问另一个数组,这会处理对它的同步访问?
谢谢,
我有两个数组,我需要跨线程同步对它们的访问。我将把它们放在一个同步块中。问题是,我只能一次性将其中之一传递给“同步”。
如何确保对两个阵列的访问是同步的?我是否将它们放在一个类中并创建一个对象?或者我只在同步块中访问另一个数组,这会处理对它的同步访问?
谢谢,
无论您做什么,都不要这样做:
synchronized (array1) {
synchronized (array2) {
// do stuff
}
}
除非您非常小心,否则这很可能导致死锁。如果你采用这种方法,你必须确保你对对象有一个不变的偏序——谷歌“Dining Philosophers”来讨论这些陷阱。
基本上,您要做的是创建一个锁定对象,如果您想访问任一数组,您将使用该对象,然后将其用于所有数组访问。它是粗粒度但安全的。你可以这样做:
public static class TwoArrays {
private int[] array1 = ...
private int[] array2 = ...
private final Object LOCK = new Object();
public void doUpdate() {
synchronized (LOCK) {
...
}
}
}
如果您需要更细粒度的方法,您想使用 Java 5+ 并发实用程序,例如,ReadWriteLock
但这将更复杂且容易出错。
在 Java 5 之前,我会这样写:
// pre Java 5 code:
Object lock = new Object();
// ...
synchronized(lock) {
// do something that requires synchronized access
}
但是从 Java 5 开始,我会使用以下类java.util.concurrent.locks
(我个人认为这并不复杂或容易出错):
// Java 5 Code Using Locks
Lock lock = // ...
lock.lock();
try {
// do something that requires synchronized access
}
finally {
lock.unlock();
}
如果您需要读写锁定,下面是使用 Java 5 中的读写锁定实现的示例:
private ReadWriteLock rwl = new ReentrantReadWriteLock();
private Lock rLock = rwl.readLock();
private Lock wLock = rwl.writeLock();
private List<String> data = new ArrayList<String>();
public String getData(int index) {
rLock.lock();
try {
return data.get(index);
} finally {
rLock.unlock();
}
}
public void addData(int index, String element) {
wLock.lock();
try {
data.add(index, element);
} finally {
wLock.unlock();
}
}
当然,根据您的需要进行调整。