【问题标题】:Is synchronized needed here这里需要同步
【发布时间】:2009-12-03 20:06:57
【问题描述】:

我有一个 java 小程序。该小程序中的一个类正在创建一个线程来完成一些工作,等待 30 秒以完成该工作,如果它在 30 秒内未完成,它会设置一个布尔值来停止线程。等待和布尔更改在一个同步块中,考虑到除了这两个之外没有其他线程在运行,这是必要的吗。

    System.out.println("Begin Start Session");
    _sessionThread = new SessionThread();
    _sessionThread.start();

    synchronized (_sessionThread)
    {
        _sessionThread.wait(30000);
        _sessionThread._stopStartSession = true;
    }

为什么我不能这样做呢。

    System.out.println("Begin Start Session");
    _sessionThread = new SessionThread();
    _sessionThread.start();

    _sessionThread.wait(30000);
    _sessionThread._stopStartSession = true;

SessionThread 运行方法。调用 JNI 方法调用 dll 打开程序窗口。

public void run()
{
    try
    {
        startExtraSession();
    } 
    catch (Throwable t)
    {
        t.printStackTrace();
    }
        notify();
}


private native void openSessionWindow(String session_file);

private void startExtraSession()
{
    final String method_name = "startExtraSession";

    String title = _sessionInfo._title;
    long hwnd = 0;

    openSessionWindow(_sessionInfo._configFile);

    try
    {
        //Look for a window with the predefined title name...
        while ((hwnd = nativeFindWindow(title)) == 0 && !_stopStartSession)
        {
            Thread.sleep(500);
    }
    }
    catch(Throwable t)
    {
       t.printStackTrace();
    }
}

1.真的需要同步吗?
2。除了使用线程之外,有没有更好的方法来实现这一点?

【问题讨论】:

    标签: java synchronization multithreading


    【解决方案1】:

    一个给定的线程需要拥有一个对象上的锁才能在其上调用wait(long)。这是通过在所述对象上使用同步块来实现的。

    请参阅J2SE specification,了解如何使用wait

    在 java 中获取锁/监视器可以通过多种方式完成:

    • synchronized(非静态)方法中,线程拥有this 引用的对象上的监视器。
    • static synchronized 方法中,线程在Class<?> 描述符上为定义所述方法的类拥有一个监视器。
    • synchronized(x) 块中,线程在x 上拥有一个监视器。

    如果满足以下条件,该锁将被释放:

    • 您脱离了同步代码块(无论是方法、静态方法还是显式块)。
    • 您已调用 wait() 或其变体之一(您将在方法返回之前重新获取它)。

    这两个列表可能会省略特定案例,但至少应涵盖大部分典型用例。

    【讨论】:

    • 如果线程归他调用同步部分的类所有,那不满足这个要求吗?距离我的 Java 时代已经很久了,请多多指教。
    • 如果您不在任何同步方法或任何同步块之外,则您不拥有任何监视器,因此无法调用wait。让我编辑我的答案,以便更清楚地了解锁定/监视器获取。
    【解决方案2】:

    你需要synchronized来调用wait的原因很简单

    synchronized 确保在您拨打wait 的同时没有人拨打notifynotifyAll

    例如:线程 1

    synchronized( obj )
    {
        triggerActionOnThread2();
        obj.wait();
    }
    

    线程 2(由 triggerActionOnThread2 触发)

        ...
        synchronized( obj )
        {
            obj.notify();
        }
    

    如果您没有同步块,那么notify 可能会在wait 之前(或期间)发生,然后wait 错过notify,您可以挂起线程1。

    想象一下没有synchronized 块的上述代码块,并想象如果在调用wait 之前线程2 一直执行到notify。

    顺便说一句,当 Java 工程师的工作涉及多线程编程时,我会问这个问题。

    【讨论】:

    • 似乎同步是为了明确何时出现异常?
    • 不完全是。同步是为了保证正确的顺序。等待/通知基本上是一个信号量。您要确保一个线程首先等待,另一个线程通知第二个。
    • 我的意思是在给出的例子中。但是再看一遍之后,notify() 是在 try/catch 之后。感谢您的输入(或者是您的输出?)!
    【解决方案3】:

    能否请您发布 SessionThread 代码?如果您不拥有锁,您将无法等待,因此您需要同步 (_sessionThread) 来执行 _sessionThread.wait(30000);不知道 _sessionThread._stopStartSession = true 是怎么回事;

    【讨论】:

    • 是的,如果第二个线程运行时间超过 30 秒,则当布尔值更改时,while 将中断。也发布了其他代码
    【解决方案4】:

    如果布尔值是线程之间唯一的共享状态,则声明布尔瞬态将保证在线程之间看到对它的更改,就像访问布尔值的同步块一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多