본문 바로가기

Java/병렬 프로그래밍

(13)
자바 병렬 프로그래밍 - 자바 메모리 모델 자바 메모리 모델은 무엇이며 , 왜 사용해야 하는가? aVariable = 3 변수에 값을 할당 했을때 자바 메모리 모델은 값을 사용 할 수 있으려면 어떤 조건이 돼야 하는지 답을 알고 있다. 동기화 기법을 사용하지 않은 경우엔 메모리 대신 CPU 레지스터에 보관이 돼서 값을 못 읽을 수도 있고 캐시의 형태에 따라 할당된 값이 메모리에 실제 보관되는 시점에 차이가 있기도 하고 CPU 내부 캐시에 보관된 값이 다른 CPU 에 보이지 않을 수도 있다. 단일 스레드로 동작하는 환경에서는 JVM 이 순차적으로 동작하는 것과 동일하게 실행되도록 명시하고 있다. 멀티 스레드로 실행되는 환경에서는 성능을 크게 제한하지 않는 한 순차성이 주는 안전성과 높은 성능은 찾아보기 어렵다. 병렬 프로그램이라도 대부분은 각자의 ..
자바 병렬 프로그래밍 - 단일 연산 변수와 넌블로킹 동기화 Semapore ,ConcurrentLinkedQueue 같이 java.util.concurrent 패키지에 들어 있는 다수의 클래스는 단순하게 synchronized 구문으로 동기화를 맞춰 사용하는 것에 비교하면 속도도 빠르고 확장성도 좋다. 단일 연산 변수와 대기 상태에 들어가지 않는 넌블로킹 동기화 기법을 사용해서 그렇다. 병렬 알고리즘의 최근 연구결과를 보면 대부분 넌블로킹 알고리즘 즉, 멀티 스레드 환경에서 데이터의 안전성을 보장하는 방법으로 락을 사용하는 대신 하드웨어에서 제공하는 비교 후 교환 등의 명령을 사용하는 알고리즘이다. 넌블로킹 알고리즘은 운영체제나, JVM 에서 프로세스나 스레드를 스케줄링 하거나 GC 작업 등 굉장히 많이 사용한다. 락을 기반으로 하는 방법보다 설계와 구현 모두 ..
자바 병렬 프로그래밍 - 명시적인 락 자바 5.0 전까지는 여러 스레드가 접근 하려 할 때 조율 할 방법이 synchronized 방법과 volatile 키워드 뿐이었다. 5.0에서 추가된 ReentrantLock 은 암묵적인 락으로 할 수 없는 일도 처리 할 수 있는 고급 기능을 갖고 있다. Lock과 ReentrantLock Lock 인터페이스는 여러 가지 락 관련 기능에 대한 추상 메소드를 정의하고 있다. 암묵적인 락과 달리 조건 없는 락, 폴링 락, 타임아웃이 있는 락, 락 확보 대기 상태에 인터럽트를 걸 수 도 있다. ReentrantLock 은 이 Lock 인터페이스를 구현한다. synchronized 구문과 동일한 메모리 가시성과 상호 배제 기능을 제공한다. ReentrantLock 을 확보하는건 synchronized 블록에 ..
자바 병렬 프로그래밍 - 성능, 확장성 스레드를 사용하는 가장 큰 목적은 성능을 높이려는 것이다. 스레드를 사용하면 시스템 자원을 훨씬 효율적으로 사용 할 수 있고, 어플리케이션이 시스템의 자원을 최대한 사용할 수 있게 한다. 또한 기존 작업이 진행되고 있어도 또 다른 작업을 실행 할 수 있어 응답 속도가 향상 된다. 이번장에서는 병렬 프로그램의 성능을 분석하고 모니터링하고 그 결과로 성능을 향상 시킬 수 있는 방법을 알아보자 성능에 대해 성능을 높인다는건 적은 자원을 사용하면서 더 많은 일을 한다는것이다. 작업이 CPU, 메모리, 네트웍 속도, DB 처리 속도 등 자원을 사용하면서 부족한 부분이 있을 수 있다. 작업 실행에 충분치 못한 자원때문에 성능이 떨어진다면 작업의 성능이 해당 자원에 좌우된다고 할 수 있다. 여러개의 스레드를 사용할때..
자바 병렬 프로그래밍 - 활동성을 최대로 높이기 안전성과 활동성 사이에는 밀고 당기는 관계가 있다. 안전성 확보를 위해 락을 사용하는데 , 락 순서에 따라 데드락이 발생하기도 한다. 락과 비슷하게 자원 사용량을 제한하고자 스레드풀이나 세마포어를 사용하기도 하는데, 구조를 이해하지 못하고 있담년 자원을 할당 받지 못하는 데드락이 발생하기도 한다. 이번장에서는 데드락 처럼 활동성에 문제를 주는 상황과 방지하는방법을 알아보자 데드락 '식사하는 철학자' 로 널리 알려져있다. 젓가락을 양쪽에 한짝씩 놓고 음식을 먹을땐 양쪽 걸 가져와서 먹게되는데 모두가 왼쪽을 가지고 있으면 오른쪽 젓가락을 가지려 할때 아무도 먹지 못하는 데드락 상황이 발생한다. 스레드 A 가 특정 락 L 을 잡고 있고 두번째 락M을 기다리고 있는 상태에서 스레드 B 가 M 을 잡고 있고 L ..
자바 병렬 프로그래밍 - 스레드 풀 활용 이번 장에서는 스레드 풀을 설정하고 튜닝하는데 사용 할 수 있는 고급 옵션을 보자 작업과 실행 정책 간의 보이지 않는 연결 관계 Executor 프레임웍이 작업의 정의 부분과 실행 부분을 서로 분리 시켜 준다고 계속 말해왔다. 하지만 Executor 프레임웍이 어느 정도의 유연성을 갖고 있지만, 특정 형태에서는 실행 할 수 없는 작업들이 있다. - 의존성이 있는 작업 : 독립적인 작업은 스레드 풀에서 실행시키면 아무 문제 없이 풀의 크기와 설정을 마음대로 변경 할 수 있지만 ,반면 의존성을 갖는 작업은 스레드 풀에 올려 실행 하려는 경우에는 실행 정책에 조건을 거는 셈이다. - 스레드 한정 기법을 사용하는 작업 : 단일 스레드로 동작해야 한다는 조건이 생기기 때문에 연결고리가 생긴셈 - 응답시간이 민감한..
자바 병렬 프로그래밍 - 중단 및 종료 이번장에서는 작업과 스레드가 정상적으로 완료되기 이전에 종료 시키는 방법에 대해 알아본다. 작업이나 스레드를 시작시키기는 쉽다. 근데 언제 멈출지는 작업이 끝까지 실행되어 봐야 알 수 있다. 어플리케이션을 작동하다 보면 정상적으로 멈추기 전에 멈추도록 해야 할 때가 있다. 자바에서는 강제로 멈출 수 있는 방법이 없다. 대신 인터럽트를 이용해 특정 스레드에게 작업을 멈춰 달라고 요청을 한다. 즉, 즉시 멈추는 경우는 없고 멈춰달라는 요청을 받으면 하던 작업을 모두 정리한 다음 종료 하도록 해야한다. 실행 사이클을 종료하는 문제를 적절하게 대응하면 그렇지 않은 어플리케이션과 품질에서 차이가 커진다 작업 중단 실행 중인 작업을 취소하고자 하는 경우는 여러가지다 사용자가 취소하기를 요청한 경우 : 취소 버튼을 ..
자바 병렬 프로그래밍 - 작업 실행 병렬 어플리케이션의 성능과 응답성을 높일 수 있는 방법을 보자 병렬화 할 수 있는 작업을 구분하는 방법에 대해 알아보고 병렬화한 결과를 작업 실행 프레임웍에서 실행시키는 방법도 보자 대부분 병렬 어플리케이션은 task(업무의 단위)를 실행하는 구조가 효율적으로 되어있다. 어플리케이션이 해야 할 일을 task 단위로 분류하면 프로그램 구조도 간결하고 트랜잭션의 범위를 지점해 오류에 효과적인 대응이 가능하고 작업 실행의 병렬성을 극대화 할 수 있다. 스레드에서 작업 실행 가장 먼저 해야할 일은 작업의 범위를 어디까지 할 것인가다. 어플리케이션은 충분한 속도, 빠른 반응 속도, 가능한 많은 사용자 요청 처리와 부하가 가해져도 그냥 죽어버리지 않고 부하가 늘어남에 따라 점진적으로 속도가 느려져야 한다. 이걸 위..