Java:在持有锁时创建新线程是否常见?

时间:2010-02-26 08:15:32

标签: java multithreading locking callback

我有一个问题,但与我在这里的第一个问题不完全相同:

Java: what happens when a new Thread is started from a synchronized block?

当您持有锁定时,创建start()Thread这是一种常见做法吗?

这会是代码味吗?

基本上我可以选择这样做:

public synchronized void somemethod() {

    (every time I find a callback to be notified I start a thread)   
    Thread t = new Thread( new Runnable() {
       void run() {
           notifySomeCallback();      
       }
    }
    t.start();
    ... 
    (lengthy stuff performed here, keeping the lock held)
    ...
}

或者这个:

public void somemethod() {
    (create a list of callbacks to be notified)
    synchronized(this){
      (potentially add callbacks)       
      ... 
      (lengthy stuff performed here, keeping the lock held)
      ...
    }
    (notify the callbacks without holding a lock and once
     we know the lock has been released)
}

我认为后者更好但我想知道是否存在 是第一种选择可以的情况?你有时候吗? 去做?你见过它吗?

3 个答案:

答案 0 :(得分:4)

ANSWER3:

  • 您应该始终保持锁定尽可能短。因此,当存在“损坏”资源的可能性时(例如,写入程序线程正在更新资源),只有在多个线程中可能引用的资源应该被锁定最短的时间

  • 不要为每个需要完成的小事件分离一个线程。在回调线程的情况下,让一个回调线程处理一系列事情。

答案 1 :(得分:3)

您知道这两个代码段将导致不同的执行顺序。 第一个将异步运行回调,而正在执行冗长的东西。第二个将首先完成冗长的工作,然后调用回调。

哪一个更好取决于回调需要做什么。如果他们需要首先完成冗长的工作,这可能是一个问题。

谁在等锁? 如果回调需要锁定运行,那么在你仍然保持锁定时触发它们是没有意义的。他们所要做的只是等待很长时间才能完成。

此外,在第一个代码段中,每个回调都有一个主题。第二个片段不明确,但如果你只有一个线程,这是另一个区别 (回调是同时运行还是按顺序运行)。如果他们都需要相同的锁,你也可以按顺序运行它们。

如果要使用一个或多个线程运行多个回调,请考虑使用Executor而不是自己管理线程。使配置适当数量的线程变得非常容易。

答案 2 :(得分:2)

这取决于你是否希望回调与冗长的东西同时执行。如果我们讨论的是Swing GUI,那么选项1并不好,因为你不应该在几个并发线程中进行Swing操作,所以我建议如下:

public void somemethod() {   
   Thread t = new Thread( new Runnable() {
       void run() {
           synchronized(this) {
             doLengthyStuff();
           }
       }
    }
    t.start();

    (notify the callbacks)
}