首页 > 解决方案 > 运行时之前未知的多个对象作为 Java 线程的锁

问题描述

我有一组资源,它们是Resource类的实例。系统中有作业在运行时进入。每个作业都需要一组这些资源,并且必须独占使用它继续进行所需的所有资源。也就是说,为了让作业能够启动,它必须获取它需要的所有资源的锁,并在完成后释放它获取的所有这些锁。因此,除非它需要的所有资源的所有锁都可用,否则作业无法开始其处理。

作业需要的资源在运行时之前是未知的。作业需要的资源列表作为Collection ArrayList<Resource>.

这样做的一种方法是,在run()每个作业线程的方法中,我可以同步“这个”作业所需的所有资源的锁。

synchronized (resource1) {
    synchronized (resource2) {
        ...

    }
}

但这是硬编码并且无法完成,因为作业所需的资源仅在运行时才知道。

我能想到的另一种方法是将资源放在集合结构中,这样,当获取该集合的锁时,该集合中所有条目的锁也会被获取,并且其他任何人都无法使用。

Collections.synchronizedList()。但是,它只锁定List,而不锁定列表中的对象。

如何才能做到这一点?

TIA。

标签: javamultithreadinglocks

解决方案


使用循环怎么样,您在运行时遍历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 循环中获取下一个可用对象的锁。


推荐阅读