-5

ビジネス フローのどこかで、スレッドがロックされています。その後、すべてが待機状態になります。このようになった場合、アプリケーションを中断せずに続行するにはどうすればよいですか。つまり、アプリケーションを終了したくないということです。実は面接の質問です。

4

2 に答える 2

1

何よりもまず、deadlocksウィキペディアのエントリをよく読むことを強くお勧めします。特に、デッドロック処理に関するセクション。

これがインタビューの質問として意図されている場合、インタビュアーは、デッドロックがどのように発生するか、およびデッドロックをどのように防止および/または解決できるかについての候補者の知識に関心を持つ可能性があります。

オブジェクトのセットで同期を使用して Java デッドロックを作成する基本的な例を次に示します。

private static void synchronizedBlockDeadlock()
{
    final Object resource1 = new Object();
    final Object resource2 = new Object();

    Runnable thread1 = new Runnable()
    {

        public void run()
        {
            synchronized (resource1)
            {
                final int sleepTimeMs = 1000;
                try
                {
                    Thread.sleep(sleepTimeMs);
                }
                catch (InterruptedException e) {}

                synchronized (resource2)
                {
                    System.out.println("In thread1");
                }
            }
        }
    };

    Runnable thread2 = new Runnable()
    {

        public void run()
        {
            synchronized (resource2)
            {
                final int sleepTimeMs = 1000;
                try
                {
                    Thread.sleep(sleepTimeMs);
                }
                catch (InterruptedException e) {}

                synchronized (resource1)
                {
                    System.out.println("In thread2");
                }
            }
        }
    };

    new Thread(thread1).start();
    new Thread(thread2).start();
}

まず、両方のスレッドが (事実上) 同時に実行されています。スレッド 1 はリソース 1 へのロックを取得し、しばらくスリープします。これを有効にすると、スレッド 2 がリソース 2 へのロックを取得します。これはもちろん、スレッド 1 のスリープ呼び出しが戻る前にスレッド 2 が開始できるという仮定に基づいています。ここで、スレッド 2 は、スレッド 1 によって保持されているリソース 1 のロックを取得しようとするため、無期限にブロックされます。スレッド 1 が起動し、スレッド 2 が保持しているリソース 2 のロックを取得しようとします。両方のスレッドが他方でブロックされるため、すべてのスレッドがデッドロックされます。

現在、このコードは、('synchronized' キーワードによるリソース オブジェクト インスタンスの暗黙的なロックとは対照的に) 明示的なロックを使用してデッドロックを防ぐために作り直すことができます。

以下のコードを参照してください。

private static void explicitLockDeadlock()
{
    final Lock lock1 = new ReentrantLock();
    final Lock lock2 = new ReentrantLock();

    Runnable thread1 = new Runnable()
    {

        public void run()
        {
            try
            {
                lock1.tryLock(5, TimeUnit.SECONDS);
                System.out.println("Thread-1: Lock 1 acquired");

                final int sleepTimeMs = 1000;
                Thread.sleep(sleepTimeMs);

                lock2.tryLock(5, TimeUnit.SECONDS);
                System.out.println("Thread-1: Lock 2 acquired");
            }
            catch (InterruptedException e) {}
            finally
            {
                lock1.unlock();
            }

            System.out.println("In thread1");
        }
    };

    Runnable thread2 = new Runnable()
    {

        public void run()
        {
            try
            {
                lock2.tryLock(5, TimeUnit.SECONDS);
                System.out.println("Thread-2: Lock 2 acquired");

                lock1.tryLock(5, TimeUnit.SECONDS);
                System.out.println("Thread-2: Lock 1 acquired");
            }
            catch (InterruptedException e) {}
            finally
            {
                lock2.unlock();
            }

            System.out.println("In thread2");
        }
    };

    new Thread(thread1).start();
    new Thread(thread2).start();
}

このアプローチは、デッドロックの可能性があるスレッドを横取りする、または 4 つのコフマン条件の「横取りしない」条件を破るインスタンスです。実際には、待機中の「tryLock」呼び出しは、指定された期間が経過すると期限切れになり、アプリケーションが無期限にハングするのを防ぎます。

于 2013-06-15T20:23:54.997 に答える