Възможно ли е програмно изтегляне на простичка ситуация с WAIT ?

+8 гласа
111 прегледа
попитан 2016 юни 10 от Nikola.Nikolov. (3,100 точки)

Въпросът ми е дали е възможно в Java да разбера дали 1 thread ще чака за заключване (lock) и да се дръпне (pullout) веднага, в случая дали ще чака за lock-ване?

Пример:

public void f() { 

  synchronized(this) { 

   //long tasks 

  }

}

Ако Thread-A все е в синхронизиран блок (synchronized block), Thread-B влиза, lock-а не е на разположение веднага,затова решава да се pull out-не (или чака Х секунди и след това се дърпа) и  да пробва наново.

Предполагам не е възможно с примитивно lock-ване със синхронизиран блок, но искам да питам за идеи за това ако 1 thread не иска да влиза в чакащ режим (WAIT state) или дали е възможно насила да pull out-нем thread от неговия WAIT режим.

В смисъл, възможно ли е да напишем нещо в Thread-B или Thread-A в този случай?

2 отговори

+2 гласа
отговорени 2016 юни 11 от Daniel Ivanov (11,160 точки)

Един вариант би бил да ползваш Object.wait(long timeout). Thread-ът ще си спре да чака след указаното му време или когато е уведомен (през Object.notify()). Така рънващия thread може да call-не notify() преди да е готов да сигнализира на чакащия thread да продължи (и да не чака докато не изтече таймаут-а).

За да махнеш thread oт рамките на друг, можеш да call-неш Thread.interrupt()  на thread-а, който държи lock-а (като имаме предвид,че InterruptedException-а не е игнориран в този thread); този подход е малко „екстремен” и не мисля, че ще свърши работа.

Всичко това става с помощта на „примитивни“ синхронизиращи tool-ове. Можеш да постигнеш (даже повече) като ползваш java.util.concurrent.Lock и Condition-и.

0 гласа
отговорени 2016 юни 13 от G.Ivanoff. (920 точки)

Да,възможно е да ползваш примитивни от java.util.concurrent  package-a, и в случая можеш да изполваш ReentrantLock, който емулира стандартен синхронизиран блок , но също така има и tryLock метод с таймаут.

ReentrantLock lock = new ReentrantLock();

public void f() {

    try {

        if (lock.tryLock(10, TimeUnit.SECONDS)) {

            try {

              //you have the lock here...

            } finally {

                //unlock

                lock.unlock();

            }

        } else {

            //pull-out

        }

    } catch (InterruptedException e) {

        e.printStackTrace();

    }

}

...