9

所以我有类似的代码

synchronized(objectOne){ do stuff }
synchronized(objectTwo){ do stuff }

这样做的问题是程序将等待 lock on objectOne,即使 lock forobjectTwo可用。我要做的是说:尝试同时锁定objectOneobjectTwo,并且无论您先获得哪个锁,都可以为该锁做些事情。我想出了一个解决方案,但我认为它相当hacky,我想知道是否有人有更好的想法。

这是我的想法:启动 2 个线程,每个线程等待一个锁,然后主线程将等待一个CountDownLatch。所以你最终会得到这样的结果:

CountDownLatch latch = new CountDownLatch(2);

new Thread(new Runnable(){
public void run(){
    synchronized(objectOne) { do stuff }
    latch.countDown();
}).start();

new Thread(new Runnable(){
public void run(){
    synchronized(objectTwo) { do stuff }
    latch.countDown();
}).start();

latch.await();
4

4 回答 4

5

我认为你应该使用Lockwhich 为你提供的方法boolean tryLock()

返回:如果获得了锁,则返回 true,否则返回 false

当你至少有一把锁时,继续做事。

于 2012-11-15T02:02:07.623 回答
2

You might want to have 2 queues of jobs, 2 threads each polling a queue and execute the jobs.

For jobs related to objectOne, you put it in queue#1; jobs related to objectTwo in queue#2.

worker1.queue.put( new Runnable(){ public void run() { do stuff } } );
worker2.queue.put( new Runnable(){ public void run() { do stuff } } );

----

class Worker extends Thread

    BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

    public void run()
        while(true)
            queue.take().run();
于 2012-11-15T02:14:06.973 回答
0

根据数量的不同,stuff分拆多个线程来做事情可能会产生更多的开销。如果stuff操作足够快,最好在单个线程中执行操作。你得花点时间才能知道。

于 2012-11-15T02:47:31.347 回答
0

我有点喜欢你的黑客,至少如果这是一次性的情况。那就是说...

如果您经常做这种事情并且想要“不那么老套”的东西,我建议您ExecutorService#invokeAll()。这需要一个 Callables 列表,在线程池上执行它们并阻塞,直到它们全部完成。

草图:

ExecutorService es = Executors.newCachedThreadPool(); // for example...
List<Future<Void>> results = es.invokeAll(new ArrayList {{ 
        add(new Callable<Void> { 
            public Void call() { synchronized(objectOne) { do stuff } }
        });
        add(new Callable<Void> { 
            public Void call() { synchronized(objectTwo) { do stuff } }
        });
    }});
// both Callables are done when you get here

这显然假设在您的应用程序中此时可以从不同的线程调用这些方法。如果由于某种原因您需要从同一个线程调用两者,我认为您注定要使用tryLockBhesh Gurung 的回答中讨论的忙等待。

于 2012-11-15T05:09:48.800 回答