Java Adv 16 - 동시성 컬렉션이 필요한 이유
in Programming Language on Java
컬렉션 프레임워크는 원자적인 연산을 제공할까?
예를 들어서 ArrayList가 인스턴스에 여러 스레드가 동시에 접근을 한다면? 참고로 스레드가 동시에 접근을 해도 괜찮은 경우를 스레드 세이프 하다고 한다. 그렇다면 ArrayList는 스레드 세이프 할까? 예제 코드로 확인 해보자
여기서는 멀티스레드를 사용하지 않지만, **스레드1과 스레드2가 동시에 다음 코드를 실행한다고 가정**해보자. 스레드1: list 에 A 를 추가한다. 스레드2: list 에 B 를 추가한다. 컬렉션에 데이터를 추가하는 add() 메서드를 생각해보면, 단순히 컬렉션에 데이터를 하나 추가하는 것뿐이다. 따라서 이것은 마치 연산이 하나만 있는 원자적인 연산처럼 느껴진다. 원자적인 연산은 쪼갤 수 없기 때문에 멀티스레드 상황에 문제가 되지 않는다. 물론 멀티스레드는 중간에 스레드의 실행 순서가 변경될 수 있으므로 [A, B] 또는, [B, A]는 변경될 수 있지만, 결과적으로 데이터는 모두 안전하게 저장될 것 같다. 하지만 컬렉션 프레임워크가 제공하는 대부분의 연산은 원자적인 연산이 아니다.
구현
가장 간단한 컬렉션의 구현이다. 내부에서는 배열을 사용해서 데이터를 보관한다. ArrayList:최소 구현 버전이라 생각하면 된다. DEFAULT_CAPACITY: 최대 5의 데이터를 저장할 수 있다. (필드 값으로 구현을 해두었다.) size: 저장한 데이터의 크기를 나타낸다. add(): 컬렉션에 데이터를 추가한다. sleep(100): 잠시 기대한다. 이렇게 하면 멀티스레드 상황에 발생하는 문제를 확인하기 쉽다. 단일 스레드로 실행했기 때문에 아직까지는 아무런 문제 없이 잘 작동한다. 과연 멀티스레드 환경에서는 어떨까?
코드에 sleep을 준 이유는?
스레드 간 자원 경쟁: 여러 스레드가 동일한 자원(예: 변수, 객체, 데이터베이스 등)을 접근하려고 할 때, sleep()을 사용하면 자원에 접근하는 타이밍을 다르게 하여 경쟁 상황을 의도적으로 유발할 수 있다. 이로 인해 동기화 문제가 발생하는지 확인할 수 있다. (의도적으로 타이밍을 다르게 준 것)
Reference
김영한님의 자바 강의