Блокировка в многопоточности Java не работает

  //I have this main class

    package IntroductionLocks;

    public class Intro {

        public static void main(String[] args) {
            NoLockATM noLockATM = new NoLockATM();
            LockedATM lockedATM = new LockedATM();
            MyClass thread1 = new MyClass(noLockATM, lockedATM);
            MyClass thread2 = new MyClass(noLockATM, lockedATM);

            thread1.start();
            thread2.start();

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            thread1.waitUntilDone();
            thread2.waitUntilDone();

            System.out.println("NoLock ATM: " + noLockATM.getBalance());
            System.out.println("Locked ATM: " + lockedATM.getBalance());
            int v = thread1.delta + thread2.delta + 100;
            System.out.println("Should Be: " + v);
            System.out.println("Program terminating.");
        }

    }


    //// 2nd class

    package IntroductionLocks;

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

    import CtCILibrary.AssortedMethods;

    public class MyClass extends Thread  {
        private NoLockATM noLockATM;
        private LockedATM lockedATM;
        public int delta = 0;

        private Lock completionLock;

        public MyClass(NoLockATM atm1, LockedATM atm2) {
            noLockATM = atm1;
            lockedATM = atm2;
            completionLock = new ReentrantLock();
        }

        public void run() {
    //question here
            completionLock.lock();
            int[] operations = {10,20};//AssortedMethods.randomArray(20, -50, 50);
            for (int op : operations) {
                System.out.println(Thread.currentThread().getName());
                delta += op;
                if (op < 0) {
                    int val = op * -1;
                    noLockATM.withdraw(val);
                    lockedATM.withdraw(val);
                } else {
                    noLockATM.deposit(op);
                    lockedATM.deposit(op);              
                }
            }
            completionLock.unlock();
        }

        public void waitUntilDone() {
            completionLock.lock();
            completionLock.unlock();
        }
    }


//// 3rd class LockedATM

package IntroductionLocks;

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

public class LockedATM {
    private Lock lock;
    private int balance = 100;

    public LockedATM() {
        lock = new ReentrantLock();
    }

    public int withdraw(int value) {
        lock.lock();
        int temp = balance;
        try {
            Thread.sleep(100);
            temp = temp - value;
            Thread.sleep(100);
            balance = temp;
        } catch (InterruptedException e) {      }
        lock.unlock();
        return temp;
    }

    public int deposit(int value) {
        lock.lock();
        int temp = balance;
        try {
            Thread.sleep(100);
            temp = temp + value;
            Thread.sleep(100);
            balance = temp;
        } catch (InterruptedException e) {      }
        lock.unlock();
        return temp;
    } 

    public int getBalance() {
        return balance;
    }
}

у меня вопрос ... почему завершениеLock.lock () в методе запуска не блокирует ресурс. Когда я запускаю программу, в System.out.println (Thread.currentThread (). GetName ())

я получаю ниже результат: Нить-1 Тема-0 Тема-0 Нить-1 Банкоматы NoLock: 130 Заблокирован банкомат: 160 Должно быть: 160 Завершение программы.

    `enter code here`isnt lock supposed to lock the resource....that mean only one thread can get access to it at a time.....????? then why it is showing that first thread 1 is getting acces then thread 0 then again thread 0 and then thread1 ???

   Isnt only thread1/0 should get first completed than other??

И что ждать, пока не будет сделано ???

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
847
2

Ответы 2

У каждого из ваших runnables есть собственный объект блокировки. Вот и ответ. У вас должна быть общая блокировка. Или используйте один из ваших объектов ATM в качестве замка

Проблема заключается в использовании блокировки повторного входа. В вашем случае каждый экземпляр потока MyClass будет иметь собственный экземпляр завершенияLock. Чтобы вы могли синхронизировать 2 экземпляра потока MyClass, вы должны использовать общий объект. Создайте экземпляр завершенияLock в основном методе и передайте его обоим потокам.

new MyClass(noLockATM, lockedATM, completionLock);

public MyClass(NoLockATM atm1, LockedATM atm2, ReentrantLock completionLockArg) {
         this.noLockATM = atm1;
         this.lockedATM = atm2;
         this.completionLock = completionLockArg; 
}

поэтому, потому что всякий раз, когда вызывается конструктор myclass, создается новая блокировка из-за завершенияLock = new ReentrantLock (); ... Итак, что я делаю из этого, это .... блокировка ресурса зависит от экземпляра класса .... здесь в моем случае .. есть 2 экземпляра myclass, и чтобы оба синхронизировались, оба должны иметь один и тот же объект блокировки ???? поправьте меня, если я ошибаюсь .. также можете указать значение метода waituntildone ??

waqas 05.10.2018 14:53

Да ... вы правильно поняли ... для того, чтобы любой набор потоков работал синхронно., Он должен быть на объекте блокировки, который доступен для всех потоков. Кроме того, я не вижу значения объявленного вами метода waitUntilDone. Он просто блокирует и разблокирует повторный вход и никоим образом не помогает для синхронизации.

Vinay Kashyap 06.10.2018 21:09

Другие вопросы по теме