You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
동시성 컬렉션이 필요한 이유 - 시작
1. 코드
1) 인터페이스 정의
add(Object e)는 현재size위치에 값을 넣고 잠깐 대기한 뒤size를 증가시키는 방식으로 동작한다.size와elementData[size]갱신이 원자적으로 보장되지 않기 때문에 쉽게 데이터 손상이 발생할 수 있는 구조이다.toString()은Arrays.copyOf(elementData, size)를 통해 “현재 size만큼만” 잘라서 출력하기 때문에, 내부 배열의 남는 공간은 출력에서 제외된다.size가 예측 가능한 흐름으로 증가하고, 배열 인덱스도 충돌하지 않기 때문에 특별한 문제가 발생하지 않는다.sleep()을 넣었음에도 단일 스레드에서는 경합이 없으므로 결과가 안정적으로 유지된다.동시성 컬렉션이 필요한 이유2 - 동시성 문제
1. 코드
[B, null]로 나온 이유는 내부 배열의 0번 인덱스에"B"가 남아 있고, 1번 인덱스에는 아무 값도 들어가지 않았는데도size가 2로 증가했기 때문이다.2. 분석
BasicList.add()는 “배열에 저장”과 “size 증가”가 분리되어 있으며, 이 두 연산이 원자적으로 보장되지 않는다.size++연산도 원자적이지 않다.size값을 기준으로 같은 위치에 쓰거나,size++가 꼬이면서 배열 상태와size값이 불일치할 수 있다.1) 데이터가 덮어씌워지는 흐름이 발생한다
elementData[size] = e를 실행하면, 두 스레드 모두 같은 시점의size값을 읽을 수 있다.size가 0일때 읽으면, 둘 다elementData[0]에 값을 쓰게 된다.elementData[0]에 남기 때문에, "A" 또는 "B" 중 하나가 덮어씌워져 사라진 것처럼 보이는 현상이 발생한다.2) sleep()는 문제를 “만드는 것”이 아니라 “잘 드러내는 것”이다
sleep(100)은 멀티스레드 충돌을 더 자주 재현하기 위한 장치로 동작한다.sleep()이 없으면 운 좋게 스케줄링이 순차적으로 일어나서 문제가 안 보일 수도 있지만, 이는 코드가 안전해진 것이 아니라 단지 충돌 타이밍이 덜 겹친 것뿐이다.sleep()은 레이스 컨디션을 확대해서 관찰하기 쉽게 만드는 역할을 한다.3) size는 1보다는 2가 될 수 있다
sleep(100)이후에size++를 실행하기 때문에, 실제로는size++가 충돌 없이 “두 번” 수행되는 경우가 많기 때문이다.[B, null], size = 2로 나온 흐름은 다음처럼 설명할 수 있다.3. 정리
Beta Was this translation helpful? Give feedback.
All reactions