运行时之前未知的多个对象作为Java线程的锁

问题描述 投票:2回答:2

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

在运行时之前不知道作业所需的资源。作业需要的资源列表作为Collection ArrayList<Resource>传递给它的构造函数。

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

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

    }
}

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

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

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

如何才能做到这一点?

TIA。

java multithreading locks
2个回答
1
投票

如何使用循环,迭代运行时可用的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循环获取对下一个可用对象的锁定。


-1
投票

您可以为List接口编写自己的实现,并在列表中查询时锁定您的资源。

https://docs.oracle.com/javase/8/docs/api/java/util/List.html

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