Работа с ReentrantLock

Рейтинг: 0Ответов: 1Опубликовано: 16.12.2014

Насколько я понимаю, класс ReentrantLock - это альтернатива synchronized. И его задачи синхронизировать потоки, если они работают с общим обьектом.

Если что не так, поправляйте.

public class TestMultithreading{
    static int count = 0; // совместный примитив на 2 потока
    public static void main(String[] args){
        Thread t1 = new Thread(new Client());
        Thread t2 = new Thread(new Client());
        t1.start();
        t2.start();
    }
}

public class Client implements Runnable{
    Lock lock = new ReentrantLock();
    @Override
    public void run() {
        while (TestMultithreading.count <= 10) {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " " + TestMultithreading.count);
            TestMultithreading.count++;
            lock.unlock();
        }
    }

Правильно:

Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
Thread-0 10
Thread-1 0

Неправильно:

Thread-0 0
Thread-0 1
Thread-0 2
Thread-1 0
Thread-1 4
Thread-1 5
Thread-0 3
Thread-1 7
Thread-1 8
Thread-1 9
Thread-1 10
Thread-0 8

Результат выходит правильный раз через раз. Почему так?

Ответы

▲ 4Принят

Во-первых, в вашем случе каждый поток синхронизируется по своей блокировке, что никак не исключает одновременного доступа потоков к разделяемой переменной. Т.е. блокировка должна быть общей для обшей переменной.

Во-вторых, оба приведенных вами примера вывода являются не тем, что вы ожидаете, т.к. поток получает блокировку на каждую итерацию цикла, а не на весь цикл. Т.е. даже если вы перепишете код с использованием общей блокировки, вы все равно будете получать разные результаты.