След: Существенные Классы
Урок: Параллелизм
Раздел: Высокоуровневые Объекты Параллелизма
Объекты блокировки
Домашняя страница > Существенные Классы > Параллелизм

Объекты блокировки

Синхронизируемый код полагается на простой вид повторно используемой блокировки. Этот вид блокировки удобен, но имеет много ограничений. Более сложные идиомы блокировки поддерживаются java.util.concurrent.locks пакет. Мы не будем исследовать этот пакет подробно, но вместо этого сосредоточимся на его самом основном интерфейсе, Lock.

Lock объекты работают очень как неявные блокировки, используемые синхронизируемым кодом. Как с неявными блокировками, только одному потоку может принадлежать a Lock объект за один раз. Lock объекты также поддерживают a wait/notify механизм, через их связанное Condition объекты.

Самое большое преимущество Lock объекты по неявным блокировкам являются своей возможностью отступить из попытки получить блокировку. tryLock метод отступает, если блокировка сразу не доступна или прежде, чем тайм-аут истечет (если определено). lockInterruptibly метод отступает, если другой поток отправляет прерывание прежде, чем блокировка будет получена.

Давайте использовать Lock объекты решить проблему мертвой блокировки мы видели в Живом. Альфонс и Гастон обучали себя замечать, когда друг собирается поклониться. Мы моделируем это улучшение, требуя что наш Friend объекты должны получить блокировки для обоих участников перед продолжением поклона. Вот исходный код для улучшенной модели, Safelock. Чтобы демонстрировать универсальность этой идиомы, мы предполагаем, что Альфонс и Гастон столь страстно увлекаются их новооткрытой возможностью поклониться безопасно, что они не могут прекратить кланяться друг другу:


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Random;

public class Safelock {
    static class Friend {
        private final String name;
        private final Lock lock = new ReentrantLock();

        public Friend(String name) {
            this.name = name;
        }

        public String getName() {
            return this.name;
        }

        public boolean impendingBow(Friend bower) {
            Boolean myLock = false;
            Boolean yourLock = false;
            try {
                myLock = lock.tryLock();
                yourLock = bower.lock.tryLock();
            } finally {
                if (! (myLock && yourLock)) {
                    if (myLock) {
                        lock.unlock();
                    }
                    if (yourLock) {
                        bower.lock.unlock();
                    }
                }
            }
            return myLock && yourLock;
        }
            
        public void bow(Friend bower) {
            if (impendingBow(bower)) {
                try {
                    System.out.format("%s: %s has"
                        + " bowed to me!%n", 
                        this.name, bower.getName());
                    bower.bowBack(this);
                } finally {
                    lock.unlock();
                    bower.lock.unlock();
                }
            } else {
                System.out.format("%s: %s started"
                    + " to bow to me, but saw that"
                    + " I was already bowing to"
                    + " him.%n",
                    this.name, bower.getName());
            }
        }

        public void bowBack(Friend bower) {
            System.out.format("%s: %s has" +
                " bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    static class BowLoop implements Runnable {
        private Friend bower;
        private Friend bowee;

        public BowLoop(Friend bower, Friend bowee) {
            this.bower = bower;
            this.bowee = bowee;
        }
    
        public void run() {
            Random random = new Random();
            for (;;) {
                try {
                    Thread.sleep(random.nextInt(10));
                } catch (InterruptedException e) {}
                bowee.bow(bower);
            }
        }
    }
            

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new BowLoop(alphonse, gaston)).start();
        new Thread(new BowLoop(gaston, alphonse)).start();
    }
}

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Высокоуровневые Объекты Параллелизма
Следующая страница: Исполнители



Spec-Zone.ru - all specs in one place