# atomic
| | visibility | compound operations |
|:-------- | ---------- | ------------------- |
| function | volatile | atomic variable |
###### tags: `java`,`concurrent`,`volatile`
單步驟process
>ref: https://ithelp.ithome.com.tw/articles/10229833
>

i++ 非原子性 (read+write) 包含讀取 i=i+1 多步驟, multi thread不能保證結果
Reading, updating, and writing. If two or more threads try to update the value at the same time, then it may not update properly.
---
### volatile, not replacement of synchronize block

* A write to a volatile field happens-before every subsequent read of that field.
* modifying its value immediately affects the actual memory storage for the variable.
* volatile forces all threads to get latest value of the variable from main memory instead of cache.
* only read the lastest data in main memory, owing to no locking the update doesn't gaurantee thread-safe.
#### visibility:
change by one thread can be visible to other threads.
#### mutual exculsion :
one thread only can execute a block of code at a given time, or do updates on shared data.
:::info
volatile never cached => read from main memory(only visibility is confirmed)
不保證同時update時的結果


:::
#### happens before guarantee
The happens-before guarantee guarantees that: Reads from and writes to other variables cannot be reordered to occur after a write to a volatile variable, if the reads / writes originally occurred before the write to the volatile variable.
* jvm 多core進行 code reorder , volatile variable 相對其他operation的先後順序不可改變
### volatile doesn't solve race condition

---
### synchronize
* First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
* Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

```java=
synchronized (this){ //lock on this object in heap
// incrementing counter
// total of max times
for (int i = 0; i < max; i++) {
count++;
}
}
```
[範例](https://www.youtube.com/watch?v=71dgtPrbToE)
update value will write directly to main memory

---
volatile: read , field use
synchronize: read and write , only block of code and method(not field)

### atomicXXX : thread-safe, lock-free
```java=
set(int value): Sets to the given value
get(): Gets the current value
lazySet(int value): Eventually sets to the given value
compareAndSet(int expect, int update): Atomically sets the value to the given updated value if the current value == the expected value
addAndGet(int delta): Atomically adds the given value to the current value
decrementAndGet(): Atomically decrements by one the current value
```
ref:[source-stacokoverflow](https://stackoverflow.com/questions/9749746/what-is-the-difference-between-atomic-volatile-synchronized)
```java=
private AtomicInteger counter = new AtomicInteger();
public int getNextUniqueIndex() {
return counter.getAndIncrement();
}
```
The AtomicInteger class uses CAS (compare-and-swap) low-level CPU operations (no synchronization needed!) They allow you to modify a particular variable only if the present value is equal to something else (and is returned successfully). So when you execute getAndIncrement() it actually runs in a loop (simplified real implementation):
```java=
int current;
do {
current = get();
} while(!compareAndSet(current, current + 1));
//only when the compareandset's current is same as current then do the current+1, or reget the current
```
So basically: read; try to store incremented value; if not successful (the value is no longer equal to current), read and try again. The compareAndSet() is implemented in native code (assembly). 有點像optimistic concurrency
#### synchronize block
* only one thread can execute them at a time
* When using non-volatile variables within synchronized blocks, Java ensures both visibility and atomicity through the synchronized keyword.
#### synchronize block get variable
The thread will invalidate its local cache and read the latest values from main memory.
#### synchronize block flush value
Any changes made to variables within the synchronized block are flushed to the main memory, making them visible to other threads.
---
### sychronize test - non-synchronize print
```java=
public class Counter extends Thread {
int count = 0;
public void run() {
int max = 1_000_000_00;
for (int i = 0; i < max; i++) {
count++;
}
System.out.println(count); // read uncommitted like
}
}
public class CounterImpl {
public static void main(String[] args) throws InterruptedException {
// Instance of Counter Class
Counter c = new Counter();
// Defining Two different threads
Thread first = new Thread(c, "First");
Thread second = new Thread(c, "Second");
// Threads start executing
first.start();
second.start();
// main thread will wait for
// both threads to get completed
first.join();
second.join();
}
}
```
result
```
100043743 // print race with second.start(), then must larger than 1_000_000_00
199905019
```
---
### sychronize test - synchronize print
```java=
import lombok.SneakyThrows;
public class VolatileRaceConditionExample {
private int counter = 0;
@SneakyThrows
public void increment() {
synchronized (this){
System.out.println("init counter value: " + counter);
for (int i = 0; i < 1000; i++) {
counter++; // Now this is an atomic operation
}
}
Thread.sleep(500);
System.out.println("med counter value: " + counter);
}
public int getCounter() {
return counter;
}
public static void main(String[] args) {
VolatileRaceConditionExample example = new VolatileRaceConditionExample();
Runnable task = () -> {
example.increment();
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final counter value: " + example.getCounter());
}
}
```
result
```
init counter value: 0 -- any one start
init counter value: 1000 -- after first block
med counter value: 2000 -- after 2 sync block
med counter value: 2000 -- after 2 sync block
Final counter value: 2000
```