자바 Thread_10
원자적 정수
- 원자적
1
2
3
int initValue = 0;
// 원자적 정수의 입력값을 생성자에 넣음
AtomicIneger atomicIneger = new AtomicIneger(initValue);
1
2
3
4
5
6
7
8
9
10
11
12
/* 둘 다 값을 1씩 증가시킴 */
atomicIneger.incrementAndGet(); // 1을 더 한값을 반환
atomicIneger.getAndIncrement(); // 현재값을 반환하고 값을 더함
/* 둘 다 값을 1씩 감소시킴 */
atomicIneger.decrementAndGet(); // 1을 뺀값을 반환
atomicIneger.getAndDecrement(); // 현재값을 반환하고 값을 뺌
/* 값을 더함 (+역할, -역할) */
atomicIneger.addAndGet(5); // 값을 더하고 반환
atomicIneger.getAndadd(5); // 기존값을 반환하고 더함
- 락이나 동기화가 필요하지않아 경쟁상태나 데이터 경쟁이 필요없음
- 단점은 메서드 자체가 원자적인데, 다른 연산과 함꼐 사용이 어려움
Lock Free 이커머스
synchronized 통한 원자성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public static void main(String[] args) throws InterruptedException {
InventoryCounter inventoryCounter = new InventoryCounter();
IncrementThread incrementThread = new IncrementThread(inventoryCounter);
DecrementThread decrementThread = new DecrementThread(inventoryCounter);
// 더하는 쓰레드 & 빼는 쓰레드 각각 만번씩 실행
incrementThread.start();
decrementThread.start();
incrementThread.join();
decrementThread.join();
// 쓰레드가 synchronized 만나면 다른 스레드는 대기상태가 되기때문에 하나씩 실행이 되고 필드는 원자성을 확보하게되어 0이 출력
System.out.println("inventoryCounter.getItems() = " + inventoryCounter.getItems());
}
public static class DecrementThread extends Thread{
private InventoryCounter inventoryCounter;
public DecrementThread(InventoryCounter inventoryCounter) {
this.inventoryCounter = inventoryCounter;
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
inventoryCounter.decrement();
}
}
}
public static class IncrementThread extends Thread {
private InventoryCounter inventoryCounter;
public IncrementThread(InventoryCounter inventoryCounter) {
this.inventoryCounter = inventoryCounter;
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
inventoryCounter.increment();
}
}
}
public static class InventoryCounter {
private int items = 0;
public synchronized void increment() {
items++;
}
public synchronized void decrement() {
items--;
}
public int getItems() {
return item;
}
}
원자적 변수를 적용한 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public static void main(String[] args) throws InterruptedException {
InventoryCounter inventoryCounter = new InventoryCounter();
IncrementThread incrementThread = new IncrementThread(inventoryCounter);
DecrementThread decrementThread = new DecrementThread(inventoryCounter);
incrementThread.start();
decrementThread.start();
incrementThread.join();
decrementThread.join();
System.out.println("inventoryCounter.getItems() = " + inventoryCounter.getItems());
}
public static class DecrementThread extends Thread{
private InventoryCounter inventoryCounter;
public DecrementThread(InventoryCounter inventoryCounter) {
this.inventoryCounter = inventoryCounter;
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
inventoryCounter.decrement();
}
}
}
public static class IncrementThread extends Thread {
private InventoryCounter inventoryCounter;
public IncrementThread(InventoryCounter inventoryCounter) {
this.inventoryCounter = inventoryCounter;
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
inventoryCounter.increment();
}
}
}
public static class InventoryCounter {
private AtomicInteger items = new AtomicInteger(0);
public void increment() {
items.incrementAndGet();
}
public void decrement() {
items.decrementAndGet();
}
public int getItems() {
return items.get();
}
}
- 락을 사용하지않아 복잡하게 하지않고 병력적으로 수행할 수 있음
- 원자적 연산을 할 떄에만 사용해야함 !!!
- 원자적 연산은 비원자적 연산을 보호하기 위해 락을 가진 일반 정수를 사용할때보다 더 성능이 좋음
- 단점은 싱글 스레드를 사용하게되면 일반 정수사용보다 느려질 수 있음
출처 - https://kmooc.udemy.com/course/java-multi-threading/ (Java 멀티스레딩, 병행성 및 성능 최적화 - 전문가 되기 )
This post is licensed under CC BY 4.0 by the author.