1

以前の開発者の1人が作成したAndroidサービスをデバッグしていますが、彼Booleanは次のように使用しています。

public static class DownloadQueue extends LinkedHashMap  
{
    // ...
    private Boolean lock = new Boolean(false);
    // ...

    //typical notify use
    synchronized public Object addToHead(Object key, Object value)
    {
        // ...
        synchronized (lock) 
        {
            //IllegalMonitorStateException FROM HERE
            lock.notify();
        }
        // ...
        return null;
    }

    //queue machinery
    public DownloadRecord getFirst()
    {
        // we block because queue is empty
        if(this.size() == 0 || (MyApp.isInternetConnectionAvailable() == false))
        {
            try 
            {   
                lock = true;
                synchronized (lock) 
                {
                    lock.wait(30000);
                }
                lock = false;
            }
            catch (InterruptedException e) 
            {}
        //continue operating the queue
        // ...
        return value;
    }
}

私が見つけたドキュメントは、それがブロックからIllegalMonitorStateException呼び出されなかったことが原因であると示唆しています。ただし、ここでは明らかにそうではありません。の範囲が問題になるのではないか、または同期されていない割り当てが問題になる可能性があるのではないかと思いました。へのすべての参照は上記の形式であり、キュー関数に1つだけあります。notify()synchronizedlocklockwait(long)

最後の、おそらく有用な詳細:これは、デバイスにネットワークがありますが、CMSがダウンしているために発生しています。この状態でアプリをテストする機会を利用しています。失敗したダウンロードが再キューイングされるため、キューが途方もない速度で動作している可能性があると思われます。したがって、競合状態がこの障害の考えられる原因である場合は、ここでの原因である可能性があります。

ありがとう!

4

2 に答える 2

4

ロック変数を再割り当てし続けるため、ロック変数の同期が機能していません。これを行う場合、 lock = true;または lock = false;「ロック」が参照するオブジェクトを変更する場合。したがって、メソッドでロックを取得してaddToHeadから、別のスレッドがgetFirstを呼び出すと、ロックの参照がその下で変更され、notifyを呼び出すまでに他の何かを指すようになります。

于 2011-12-05T16:10:09.587 に答える
4

問題はlock、メソッドでメンバー変数の値を再割り当てしていることですgetFirst

ブール値は不変の型であるため、その値を再割り当てすると、新しいオブジェクトが作成されます。

つまり、同期したのと同じオブジェクトに通知する保証はありません(間に再割り当てが発生した場合)。

finalこの種のプログラミングエラーを回避するために、ロック変数を宣言することをお勧めします。

于 2011-12-05T16:13:07.463 に答える