我的要求如下:
1)具有所有静态方法和静态列表的类。此列表存储了一些我要对其执行操作的对象。
2)现在,从多个线程调用此操作。
3)此操作调用不共享任何公共数据,因此该方法不同步。
4)现在,无论何时使用新对象更新此列表,我都必须停止此操作调用。
class StaticClass{
static List<SomeObjects>=new List<>();
static performOperation()
{
//call operation on all objects in the list
}
static updateList()
{
//update list, add, update or remove objects
}
}
可能的解决方案:
1)使performOperation()和updateList()同步。但是,performOperation()的调用频率太高,udpate列表频率太低。
2)使用读写锁。在performOperation()中使用读锁,在updateList()中使用写锁。示例如下所示:
class StaticClass{
static List<SomeObjects>=new List<>();
static final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
static performOperation()
{
readWriteLock.readLock().lock();
//call operation on all objects in the list
readWriteLock.readLock().unlock();
}
static updateList()
{
readWriteLock.writeLock().lock();
//update list, add, update or remove objects
readWriteLock.writeLock().unlock();
}
那么哪种解决方案更好?这是读写锁的正确用法吗?为什么对方法2感到困惑,因为performOperation()中没有需要读取或写入访问的数据。当列表正在更新时,我只是无法调用此方法。因此,我不确定它是否适合使用读写锁。
答案 0 :(得分:0)
ReadWriteLock
效率更高,因为synchronized
会阻塞所有内容。也就是说ReadWriteLock
更容易出错。例如,您的示例实际上将最终陷入死锁,因为每次您调用readWriteLock.writeLock()
或readWriteLock.readLock()
时,它都会创建一个新实例,并且永远不会被解锁,从而导致它陷入死锁。因此,您的示例应更像:
class StaticClass{
static List<SomeObjects>=new List<>();
static final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
static final Lock readLock = readWriteLock.readLock();
static final Lock writeLock = readWriteLock.writeLock();
static void performOperation()
{
readLock.lock();
try {
//call operation on all objects in the list
} finally {
// This ensures read lock is unlocked even when exception occurs
readLock.unlock();
}
}
static void updateList()
{
writeLock.lock();
try {
//update list, add, update or remove objects
} finally {
// This ensures read lock is unlocked even when exception occurs
writeLock.unlock();
}
}
}
请注意,我还在此处添加了try/finally
,以避免出现异常情况。如您所见,这比简单的synchronized
部分要花很多功夫。
还有一个可能的替代方法CopyOnWriteArrayList。这是线程安全的,因此您不必使用锁或synchronized
关键字。写入大量内容时,它将影响您的性能。