Здравствуйте. Подскажите, пожалуйста, по многопоточности и блокировкам. Вот есть код Код | 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?
|