java - 运行时之前未知的多个对象作为 Java 线程的锁
问题描述
我有一组资源,它们是Resource
类的实例。系统中有作业在运行时进入。每个作业都需要一组这些资源,并且必须独占使用它继续进行所需的所有资源。也就是说,为了让作业能够启动,它必须获取它需要的所有资源的锁,并在完成后释放它获取的所有这些锁。因此,除非它需要的所有资源的所有锁都可用,否则作业无法开始其处理。
作业需要的资源在运行时之前是未知的。作业需要的资源列表作为Collection
ArrayList<Resource>
.
这样做的一种方法是,在run()
每个作业线程的方法中,我可以同步“这个”作业所需的所有资源的锁。
synchronized (resource1) {
synchronized (resource2) {
...
}
}
但这是硬编码并且无法完成,因为作业所需的资源仅在运行时才知道。
我能想到的另一种方法是将资源放在集合结构中,这样,当获取该集合的锁时,该集合中所有条目的锁也会被获取,并且其他任何人都无法使用。
有Collections.synchronizedList()
。但是,它只锁定List
,而不锁定列表中的对象。
如何才能做到这一点?
TIA。
解决方案
使用循环怎么样,您在运行时遍历Resources
可用列表,然后在每次迭代时获取对象上的锁,这是一个示例,我在Object
该类中演示了这一点:
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
list.addAll(Arrays.asList(new Object(), new Object(), new Object()));
Runnable run = () -> {
for(Object o: list) {
synchronized (o) {
System.out.println("Current thread " + Thread.currentThread().getName());
System.out.println(o.hashCode());
try {
Thread.sleep(2000);
}catch (InterruptedException ie){
ie.printStackTrace();
}
//do something useful
}
}
};
new Thread(run, "t1").start();
new Thread(run, "t2").start();
new Thread(run, "t3").start();
new Thread(run, "t4").start();
}
当一个线程获得了特定对象的锁时,其他线程将等待它,但它们可以自由地从 for-each 循环中获取下一个可用对象的锁。
推荐阅读
- pytorch - torchvision.transforms.Normalize 是如何运作的?
- android - Android Webview + Jquery datatables 按钮:pdf导出变成bin文件
- ubuntu - sam local start-api go lambda 在 linux ubuntu 上返回 502“内部服务器错误”
- flutter - 如何在flutter中使用继承的小部件更新第二个时刷新旧屏幕
- r - RSelenium没有打开浏览器
- javascript - 避免在结果中获取 id 数组(mssql - node.js)
- postgresql - 修改现有查询
- oracle-cloud-infrastructure - 有没有简单的方法可以删除 Oracle 云基础设施隔间中的所有资源?
- javascript - 未定义不是对象(评估“state.markers”)
- java - OpenJDK和Oracle JDK之间computeIfAbsent的语义差异