При выполнении следующего фрагмента кода я вижу, что результаты становятся все правильно и однозначно порядковым однако они печатаются в порядке (как показано ниже):Действительно ли атомизация в Java гарантирует заказ или только уникальность?
import java.util.concurrent.atomic.AtomicInteger;
public class Atomics {
private AtomicInteger index = new AtomicInteger(0);
public static void main(String [] args) {
new Atomics().updateIndexViaCAS();
}
private void updateIndexViaCAS() {
Runnable target =() -> {
for(int i = 0; i<10;i++) {
cas:
while (true) {
int oldValue = index.get();
int newValue = oldValue + 1;
if(index.compareAndSet(oldValue, newValue)) {
System.out.println(Thread.currentThread() + ": "+newValue); //order is not guaranteed?
break cas;
}
}
}
};
/*Runnable target =() -> {
for (int i = 0; i < 10; i++) {
int oldValue = index.get();
int newValue = oldValue + 1;
do {
oldValue = index.get();
} while (!index.compareAndSet(oldValue, newValue));
System.out.println(Thread.currentThread() + ": "+newValue);
}
};*/
for(int t=0; t<2;t++) {
Thread th = new Thread(target);
th.start();
}
}
}
Sample Результаты:
Thread[Thread-0,5,main]: 1
Thread[Thread-0,5,main]: 3
Thread[Thread-0,5,main]: 4
Thread[Thread-0,5,main]: 5
Thread[Thread-0,5,main]: 6
Thread[Thread-1,5,main]: 2 <-- out of order
Thread[Thread-0,5,main]: 7
Thread[Thread-0,5,main]: 9
Thread[Thread-0,5,main]: 10
Thread[Thread-0,5,main]: 11
Thread[Thread-0,5,main]: 12
Thread[Thread-1,5,main]: 8 <-- out of order
Thread[Thread-1,5,main]: 13
Thread[Thread-1,5,main]: 14
Thread[Thread-1,5,main]: 15
Thread[Thread-1,5,main]: 16
Thread[Thread-1,5,main]: 17
Thread[Thread-1,5,main]: 18
Thread[Thread-1,5,main]: 19
Thread[Thread-1,5,main]: 20
ли потому что:
С кодом что-то не так (и если да, то как его исправить для обеспечения порядка)?
Является ли это правильным поведением атомистики, потому что по дизайну они не гарантируют выполнение заказа, а только гарантируют бесконтактный параллелизм?
Что-то еще на работе здесь?
TIA.
Чтобы устранить мое замешательство с комментариями ниже - зачем мне Atomic в первую очередь, если мне все еще нужно использовать синхронизацию, чтобы посмотреть, что происходит, как показано ниже?
Runnable target =() -> {
for (int i = 0; i < 10; i++) {
cas: while (true) {
synchronized (mutex) {
int oldValue = index.get();
int newValue = oldValue + 1;
if (index.compareAndSet(oldValue, newValue)) {
System.out.println(Thread.currentThread() + ": "
+ newValue); // order is not guaranteed?
break cas;
}
}
}
}
};
Порядок, в котором 'index' принимает свои значения, необязательно является порядком, в котором происходят вызовы' println'. 'CompareAndSet' является атомарным; 'compareAndSet'-and-println - нет. – user2357112
Это # 2. Атомные переменные обеспечивают атомарность обновлений и видимость обновлений. Они не имеют никакого отношения к заказу. –
@ 4castle: значит, это означает, что атомный CAS действительно ничего не покупает, так как мне еще нужно синхронизировать, чтобы посмотреть, что мне интересно видеть через 'println'? Или что? Примеры кода оцениваются. –