30
concurrent Programming #1 코코코코코 코코코

Concurrent programming

Embed Size (px)

Citation preview

Page 1: Concurrent programming

concurrent Program-ming #1

코딩소림사 강병수

Page 2: Concurrent programming

왜 concurrent programming 인가 ?

• 10 년 전 컴퓨터나 지금 컴퓨터나 cpu 처리속도는 도찐개찐• 대신에 core 개수가 늘어남• cpu 개수가 2 배 늘어났으니 연산도 2 배 빨리 끝나겠지 ?

VS

Page 3: Concurrent programming

왜 concurrent programming 인가 ?

• 둘이 합쳐 IQ 300 이 될 수 없듯이• 코어를 늘린다고 저절로 어플리케이션 성능이 좋아지지는 않는다

Page 4: Concurrent programming

멀티코어 컴퓨팅은 어렵다 ?

Page 5: Concurrent programming

• thread 문제들• thread safety (= 리소스 동기화 )• 기대하지 않는 동작

• 동기화 방식과 성능 병목• mutex / semaphore / spin lock• lock-free / wait-free

• Java 는 동기화를 어떻게 하나요 ?• monitor(=synchronized)• Lock(ReentrantLock, ReentrantReadWriteLock)

• thread 문제 해결을 위한 다른 접근• h/w transactional memory• functional programmaning

Page 6: Concurrent programming

다수의 core 를 사용하는 방법• multi processing• multi threading

이 두 가지 밖에 없다 .

Page 7: Concurrent programming

process vs thread

• 생성 / 삭제 비용• 리소스 공유

• heap / static / global

Page 8: Concurrent programming

thread safety• 모든 thread safety 문제는 공유되는 리소스 간 동기화 문제• 다음 4 가지 상황을 만족하면 thread safe• 공유 리소스 없다• 공유 리소스 있다 & immutable• 공유 리소스 있다 & critical section 에 대한 동기화 보장• 공유 리소스 있다 & atomic operation

Page 9: Concurrent programming

동기화 메커니즘을 이해하기 위한 분류• 동기화 메커니즘 제공자가 누구니 ?

• kernel level lock• user level lock

• 사용 책임자가 누구니 ?(= 발로 짜도 잘 돌아가니 ?)• application 개발자• system 또는 language spec(= 개발자 아님 )

• 취급 주의사항이 있니 ?• recursion 금지• 오랜 점유 금지

• ( 시나리오에 따라 ) 성능이 어떻게 달라지니 ?• 다수의 thread 가 경쟁• 매우 짧은 critical section / 혹은 그 반대

Page 10: Concurrent programming

상황에 맞는 동기화 메커니즘

• 동기화 메커니즘을 일일이 살펴보는 이유• 상황에 맞게 동기화 전략을 세우기 위해• 닭 잡는데 소 잡는 칼을 쓰지 말자

Page 11: Concurrent programming

mutex(Mutual Exclusion)• mutex 라고 하면 두 가지를 지칭한다 .• 이론 : 동기화 방법론 / algorithm• 구현

• 플랫폼마다 다르다 .• pthread : pthread_mutex_init, pthread_mutex_lock, …• windows : CreateMutex, OpenMutex, …• 등등등…

• mutex 를 간단히 설명하면• kernel 이 제공하는 무한 loop• 단 1 개의 thread 만 무한 loop 를 통과할 수 있고 , 나머지는 sleep

Page 13: Concurrent programming

mutex(Mutual Exclusion)• https://github.com/GerHobbelt/pthread-win32/blob/master/pthread_mutex_lock.c#L89-L

98• win32 버전의 pthread mutex 구현 – 다른 구현들도 대동소이합니다 .

Page 14: Concurrent programming

mutex(Mutual Exclusion)• mutex 의 문제• kernel wait overhead

• mutex lock/unlock 시 thread 를 sleep/wake 시키기 위한 system call• 아주 짧은 연산을 할때도 일단 thread 를 sleep/wake 시켜야 하기 때문에 비효율적

• 해결• spin lock• futex – 최근 linux kernel(2003 년 이후 ) mutex 는 모두 futex 지원

Page 15: Concurrent programming

semaphore• semaphore 도 mutex 와 마찬가지• 이론 : 동기화 방법론 / algorithm• 구현

• mutex 와 마찬가지로 플랫폼마다 다르다 .• pthread : sem_init, sem_wait, …• windows : CreateSemaphore, WaitForSingleObject, …• 등등등…

• semaphore 를 간단히 설명하면• mutex 로 구현한 resource counter• 내가 지정한 개수만큼의 thread 가 critical section 에 진입 가능

mutex 랑 다른점 !!

Page 16: Concurrent programming

semaphore

Page 17: Concurrent programming

lock 성능 개선• mutex 와 semaphore 의 공통점• kernel level lock• lock / unlock 의 비용이 크다

• kernel wait• sleep / wake wait

• kernel resource(e.g. file / shared memory …) 도 동기화 가능• lock / unlock 비용을 줄이는 방법• sleep / wake 를 하지 않거나• lock 을 직접 구현해서 쓰거나

spin lock

Page 18: Concurrent programming

spin lock• spin lock 구현도 무한 loop• thread 를 sleep 시키지 않는다• 구현이 간단하고 효과적이기 때문에 user area 에서 직접 구현하여 쓰는 경우가 많다 .• 직접 구현할 경우 , 반드시 recursion 문제를 고려하여야 한다 .

• 효과• mutex / semaphore 에 비해 응답이 빠르다 .

• 문제점• 문제 1. busy wait(=spin wait)• 문제 2. recursion 시 deadlock

https://github.molgen.mpg.de/git-mirror/glibc/blob/master/nptl/pthread_spin_lock.c#L44-L66

Page 19: Concurrent programming

spin lock 의 문제• 문제 1. 언제 busy wait 가 발생하나 ?

• 여러 threa 가 경쟁할 때• critical section 에 머무르는 시간이 길 때 (= 연산량이 많을 때 )

• 문제 2. recursion 시 deadlock• lock 을 해제하지 않고 재차 lock 을 시도하기 때문에 발생• 보통은 spin lock 내부에 call counter 를 두어 recursion 이 가능하도록 구현한다 .

• spin lock 은 다음의 경우에 유리• thread 간 리소스를 얻기 위한 경쟁이 치열하지 않고• 리소스 접근 시 연산량이 짧을 때

Page 20: Concurrent programming

lock 직접 구현• lock 을 직접 구현하였을 때 장점

• kernel wait 를 하지 않는 만큼 빠르다 .

• 문제점• 커널 리소스에 대한 동기화를 보장할 수 없다 .• 어차피 우리는 시스템 프로그래밍 안하니까 괜찮아 !

• Java 의 Lock interface 구현이 여기에 해당• ReentrantLock• ReentrantReadWriteLock

• 어떻게 lock 을 구현하나요 ?• locking algorithm 을 보고 따라하면서• processor 가 제공하는 atomic operation 을 사용합니다 .

Page 21: Concurrent programming

thread safety• 모든 thread safety 문제는 공유되는 리소스 간 동기화 문제• 다음 4 가지 상황을 만족하면 thread safe• 공유 리소스 없다• 공유 리소스 있다 & immutable• 공유 리소스 있다 & critical section 에 대한 동기화 보장• 공유 리소스 있다 & atomic operation

lockatomic operation

Page 22: Concurrent programming

atomic operation• processor 가 H/W 적으로 제공하는 연산• 해당 연산은 반드시 thread safe 함을 H/W 가 보장public class AtomicNonAtomicExample { static int foo = 0; static AtomicInteger atomicFoo = new AtomicInteger(0);

public static void main(String[] args) { foo += 1; atomicFoo.incrementAndGet(); }}

GETSTATIC atomicFooINVOKEVIRTUAL incrementAndGet ()IPOP

atomicFoo 읽기incrementAngGet() 호출 call stack 정리

atomic!!한번의 연산으로 foo 에 더하고 쓰기를 완료했다 .

GETSTATIC foo : IICONST_1IADD PUTSTATIC foo : I

foo 읽기constant 1 읽기foo 와 1 더하기 foo 에 쓰기

not atomic!!두 연산 사이에 다른 쓰레드 연산이 간섭할 수 있다 .

Page 23: Concurrent programming

atomic operation• H/W 가 제공하므로 H/W 마다 instruction set 이 다르다 .• x86 processor 에서 제공하는 atomic operation• compare and swap• test and set• fetch and add

• 대부분의 언어에서 atomic operation 을 사용할 수 있는 수단을 제공한다 .• java : java.util.concurrent.atomic

Page 24: Concurrent programming

atomic operation• 왜 쓰나요 ? • 빠르니까 !!

Page 25: Concurrent programming

atomic operation• kernel wait 없음 – > 빠르다• lock 없음 – > 무한 loop 없음 – > 빠르다• atomic operation 을 사용하는 이유 -> 빠르다• atomic operation 은 다루기 까다롭다 .• atomic operation 을 잘 사용하려면 알아둬야 할 지식이 많다 .

좌우간 빠르다 !!

Page 26: Concurrent programming

test and set• 어떤 값 (=lock 여부를 확인하기 위한 Boolean) 을 1 로 변경 / 저장하는 operation

이해를 돕기 위한 S/W 구현 TAS 로 구현한 mutex

• x86 cpu 의 TAS 구현은 BTS(bit test and set)• http://www.felixcloutier.com/x86/BTS.html

Page 27: Concurrent programming

test and set

Page 28: Concurrent programming

compare and swap• 가장 만만하게 쓰임• 저장공간에 실제 저장된 값 (a) 과 예상되는 값 (b) 를 비교하여

• a == b 이면 a 를 내가 변경하고 싶은 값 (c) 로 변경 후 true를 리턴• a != b 이면 실패 , false 를 리턴

이해를 돕기 위한 S/W 구현

• x86 cpu 의 CAS 구현은 CMPXCHG(compare and exchange)• http://x86.renejeschke.de/html/file_module_x86_id_41.html

Page 29: Concurrent programming

ABA problem• 아주 우연히 재수가 없으려니 발생하는 현상• 그런데 그것이 실제로 일어났습니다 ?

• 원인• CAS 의 동작원리에 따라 , 기대값 == 실제값 인 경우 데이터를 변경 . 허나 실제로 데이터를 변경하면 안되는 상황일 수 있다 .• 링크드리스트 node 의 reference 가 우연히 재사용되어

CAS instruction 이 변경을 감지하지 못함• 대체로 수십만 번 정도의 동시 접근이 일어날 때 발생 -> 많지도 않지만 적지도 않은 빈도• 다행스럽게도 java 에서는 발생하지 않습니다 .• 다행스럽게도 java concurrent collection 구현에서는 발생하지 앖습니다 .• 그럼 몰라도 되겠네 ?

Page 30: Concurrent programming

다음 시간에는• Java thread implementation• Synchronized vs Lock• Runnable vs Callable• executorService 와 thread pool• Future

• Why functional?