Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Java Concurrency. Как заблокироваться по объекту.


Автор: w3xgamer 4.10.2020, 15:14
Здравствуйте. 
Подскажите, пожалуйста, по многопоточности и блокировкам. 

Вот есть код
Код

package org.study.java.concurrency;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;


class SomeDataClass  {
    private final AtomicLong number1;
    private final AtomicLong number2;


    public SomeDataClass(Long number1, Long number2) {
        this.number1 = new AtomicLong(number1);
        this.number2 = new AtomicLong(number2);

    }

    public synchronized void NextStep() {
        synchronized (this) {
            this.setNumber1(getNumber1() + 1);
            this.setNumber2(getNumber2() + 1);
        }
        Thread.yield();
     }

    public synchronized Long getNumber1() {
        return number1.get();
    }

    public synchronized Long getNumber2() {
        return number2.get();
    }

    public synchronized void setNumber1(Long number1) {
        this.number1.set(number1);
    }

    public synchronized void setNumber2(Long number2) {
        this.number2.set(number2);
    }
}

class ProcessRunner implements Runnable {

    private final SomeDataClass dataClass;

    public ProcessRunner(SomeDataClass dataClass) {
        this.dataClass = dataClass;
        System.out.println("CameDataClass to ProcessRunner = " + dataClass);
        System.out.println("With values, number1 = " + dataClass.getNumber1() + ", number2 = " + dataClass.getNumber2());
    }

    @Override
    public void run() {
        while (true) {
            dataClass.NextStep();
        }
    }
}

class ProcessChecker implements Runnable {
    private final SomeDataClass dataClass;

    public ProcessChecker(SomeDataClass dataClass) {
        this.dataClass = dataClass;
        System.out.println("Came dataclass to process checker = " + dataClass);
        System.out.println("With values, number1 = " + dataClass.getNumber1() + ", number2 = " + dataClass.getNumber2());

    }

    @Override
    public void run() {
        try {
            while (true) {
                System.out.println("DataClass = " + dataClass + ",  CurrentNumber1 = " + dataClass.getNumber1() + ", CurrentNumber2 = " + dataClass.getNumber2());
                TimeUnit.SECONDS.sleep(2);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


public class ConcurrencyExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        SomeDataClass dataClass = new SomeDataClass(1L, 1L);
        executorService.submit(new ProcessRunner(dataClass));
        executorService.submit(new ProcessChecker(dataClass));

        executorService.shutdown();

    }
}


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

Вот, сейчас вывод примерно такой. 
Код

CameDataClass to ProcessRunner = org.study.java.concurrency.SomeDataClass@266474c2
With values, number1 = 1, number2 = 1
Came dataclass to process checker = org.study.java.concurrency.SomeDataClass@266474c2
With values, number1 = 177, number2 = 180
DataClass = org.study.java.concurrency.SomeDataClass@266474c2, CurrentNumber1 = 1024, CurrentNumber2 = 1026
DataClass = org.study.java.concurrency.SomeDataClass@266474c2, CurrentNumber1 = 2787500, CurrentNumber2 = 2787531
DataClass = org.study.java.concurrency.SomeDataClass@266474c2, CurrentNumber1 = 5828168, CurrentNumber2 = 5828509
DataClass = org.study.java.concurrency.SomeDataClass@266474c2, CurrentNumber1 = 8834895, CurrentNumber2 = 8837607

Process finished with exit code 130 (interrupted by signal 2: SIGINT)


Есть вариант решения этой проблемы через synchronized вот так
Код

            synchronized (dataClass) {
                System.out.println("DataClass = " + dataClass + ",  CurrentNumber1 = " + dataClass.getNumber1() + ", CurrentNumber2 = " + dataClass.getNumber2());
                TimeUnit.SECONDS.sleep(2);
            }


Но мне интересно как можно решить ту же самую проблему с помощью Lock и ReentrantLock?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)