|
34 | 34 | ### 경로 수 |
35 | 35 | 위 코드중 return ++lastIdUsed 라는 코드 한줄은 바이트 코드 명령 8개에 해당한다 |
36 | 36 | 만약 두 스레드가 명령 8개를 뒤섞어 실행할 경우 경우의 수는 엄청 많아지게 된다 |
37 | | -루프나 분기가 없는 명령 T개를 스레드 N개가 차례로 실행한다면 가능한 경로수는 다음과 같다 |
| 37 | + |
| 38 | +### 심층 분석 |
| 39 | +#### 원자적 연산(atomic operation)이란? |
| 40 | +중단이 불가능한 연산을 원자적 연산이라고 정의한다. 다음 예제를 살펴보자 |
38 | 41 | ``` |
39 | | - (NT)! |
40 | | ------- |
41 | | - T!ⁿ |
| 42 | +public class Example{ |
| 43 | + int lastId; |
| 44 | + |
| 45 | + public void resetId(){ |
| 46 | + lastId = 0; //원자적 연산 부분 |
| 47 | + } |
| 48 | + |
| 49 | + public void getNextId(){ |
| 50 | + ++lastId; //전처리 증가 연산 부분 |
| 51 | + } |
| 52 | +} |
42 | 53 | ``` |
| 54 | +표시한 lastId에 0을 할당하는 연산은 원자적이다. |
| 55 | +자바 메모리 모델에 의하면 32비트 메모리에 값을 할당하는 연산은 중단이 불가능하기 때문이다. |
| 56 | +하지만 만약 lastId를 int에서 long으로 바꾼다면 경우에따라 어떤 프로세서는 원자적 연산으로 처리할지도 모르지만 |
| 57 | +64비트 값을 할당하는 연산은 32비트 값을 할당하는 연산 두개로 나눠진다. 즉 첫 32비트 값을 할당한 후 둘째 32비트 값을 할당하기 직전에 |
| 58 | +다른 스레드가 끼어들어 두 32비트 값중 하나를 변경할수 있다는 의미이다. |
| 59 | + |
| 60 | +전처리 증가 연산인 ++lastId는 중단이 가능하기에 원자적연산이다. |
| 61 | +예를들어 lastId가 42였다고 가정했을시, |
| 62 | +첫째 스레드가 실행되는 도중 중단되고 둘째 스레드가 끼어들어 먼저 명령을 실행하여 43을 얻어갔다. |
| 63 | +이제 첫째 스레드가 중단했던 실행을 재개한후 1을 더해 43을 얻은후 결과를 저장한다. 첫째 스레드 역시 43을 가져간다. |
| 64 | +둘째 스레드가 증가한 값은 잃어버린다. 둘째 스레드가 첫째 스레드를 중단한 후 다시 실행된 첫째 슬드가 둘째 스레드의 작업을 덮어썼기 때문이다. |
| 65 | +getNextId() 메서드를 synchronized(동기화 : 현재 데이터를 사용하고 있는 해당 스레드를 제외하고 나머지 스레드들은 데이터에 접근 할 수 없도록 막는 개념)로 |
| 66 | +선언하면 문제는 해결되게 된다. |
| 67 | + |
| 68 | +스레드가 서로의 작업을 덮어쓰는 과정을 이해하기 위해서는 어떤 연산이 안전한지 못한지를 파악할 수 있도록 메모리 모델을 이해하고 있어야한다. |
| 69 | +즉, 아래의 3가지를 이해해야 한다. |
| 70 | + |
| 71 | + - 공유 객체/값이 있는 곳 |
| 72 | + - 동시 읽기/수정 문제를 일으킬 소지가 있는 코드 |
| 73 | + - 동시성 문제를 방지하는 법 |
| 74 | + |
| 75 | +## 라이브러리를 이해하라 |
| 76 | + |
| 77 | +### Executor 프레임워크 |
| 78 | + - 스레드 풀링으로 정교한 실행을 지원한다. |
| 79 | + - 코드가 깔끔해지고 이해하기 쉬워지며, 크기가 작아진다. |
| 80 | + - 스레드 풀 크기를 자동으로 조정하며, 재사용할 수 있다. |
| 81 | + |
| 82 | +### 스레드를 차단하지 않는 방법(non blocking) |
| 83 | + - 최신 프로세서는 blocking 하지 않고 안정적으로 값을 갱신한다. |
| 84 | + - 현대 프로세서는 [CAS(Compare and Swap)](https://chickenpaella.tistory.com/97)을 지원한다. |
43 | 85 |
|
0 commit comments