What?

동기화(同期化, synchronization)란, 말그대로 동시에 시스템을 작동시킬 수 있도록 만드는 것이다. 

그러므로 프로세스 동기화란, 멀티프로세스를 가능하게 만드는 것이다. 

이렇게 따로 용어까지 있는 정도면, 프로세스를 동시에 작동하는 것이 어떤 문제를 발생시킬 수 있을 정도로 중요한 문제가 될 수도 있다는 것이다. 바로 자원의 문제이다. 

 

 

먼저, 프로세스를 작동시키는 물리적인 주체는 cpu가 어떻게 프로세스를 작동시키는지,  자원을 어떻게 다루는지 보자..


*cpu 하나는 한번에 프로세스 하나만 처리할 수 있다.*

*프로세스는 ram 위에 작동되는 프로그램을 뜻하고, ram 위에는 프로세스마다 자신의 Code,Data,Stack에 대한 주소공간이 있다*

*cpu가 프로세스를 작동시키는 과정은 다음 그림과 같다*

'cpu'는 '프로세스의 주소공간'과 계속 데이터를 주고 받으며 동작한다. 

 

 

 

 

cpu는 하나의 프로세스 Data(on ram)에서 연산할 data를 가져와 연산을 하고, 연산 결과를 다시 Data(on ram)에 저장한다.

 

 

 

 

 

 

 

 

 

 


Issue?

그렇다. 한 프로세스의 주소공간은 다른 프로세스의 주소공간에 독립적이므로, Data 자원에 대해 문제가 생길 일이 없다. 하지만 프로세스 사이에 공유메모리(이전글)를 사용하는 경우라면, 얘기가 달라진다. 

 

예를 들어, a프로세스가 cnt란 변수를 1만큼 올렸는데, b프로세스가 cpu를 빼앗아서 cnt를 2로 올리고, 다시 a프로세스가 cpu를 빼앗으면 cnt를 1에서 이어서 올리는 것이 아닌, 2에서부터 올리게 되어 원래의 의도와 달라진다. 이것을 cpu를 빼앗기는 타이밍에 의해 Data의 일관성이 깨진다고 한다. 

 

 

Solution?

cpu가 하나인 경우) 프로세스 선택 정책을 선점이 아닌 비선점을 택하면 된다. 위의 경우에서, a프로세스가  cnt를 올리려고 했던만큼 완전히 올리기 전까진 b프로세스가 cpu를 뺏지 못하는 것을 의미한다. 

 

cpu가 여러개인 경우) 프로세서 자체가 구분되어 있어서 자원에 접근하는 것을 막을 방법이 없다. 그래서 커널에서 을 걸어서, 커널이 자원에 한 프로세스만 접근하도록 결정한다. 피터슨 알고리즘, 세마포어, 모니터가 있다. 

 

먼저, 용어에 대해 정리하고 가자. 


(lock 상호배제 or mutex or mutual exclusion):  동기화 메커니즘

 

 

Issue에서 설명한 것과 같이, 공유 자원에 대해 여러 개의 프로세스가 동시에 접근을 시도할 때 접근의 타이밍이나 순서 등이 결과값에 영향을 줄 수 있는 상태경쟁상태라고 말한다. 

 

 

 

 

 

 

공유자원 중에서도, 둘 이상의 스레드 동시에 접근해서는 안되는 코드의 일부크리티컬 섹션,임계구역, 공유변수라고 말한다. 

 


1)피터슨 알고리즘(소프트웨어적 락):

 

자신 프로세스의 turn=0, 다른 프로세스의 turn=1 일 때(각각 다른 프로세서가 맡았을 때) 0을 기준으로 while(turn!=0)은 1의 순서인 동안 루프만 돌며 임계영역에 진입하지 않는다는 뜻이다. 1의 순서가 끝났으면 자신 프로세스는 루프를 지나 critical section에 진입하고, 볼 일을 다 보면  다시 turn=1로 순서를 바꾸어준다. 다른 프로세서의 turn 1 프로세스는 자신의 차례이니 critical section에 진입한다. 

 

 

Issue->cpu는 instruction 단위로 빼앗길 수도 있어서, critical section 중도에 뺏기면  turn을 돌려놓지 않고 빼앗기는 것이기 때문에 다른 프로세스에서는  turn의 값이 바뀔때까지 기다리고, 자신 프로세스 또한 cpu를 뺏긴 상태기 때문에  <progress,진행 문제>와 <스핀락> 현상이 일어날 수도 있다.

 

progress,진행 문제:  아무도 critical section에 들어가지 않는 상태

스핀락,바쁜대기: critical section에 진입이 가능할 때까지 루프를 돌면서 재시도하는 상태(cpu와 메모리를 계속 써서 낭비함)

더보기

스핀락은 운영 체제 스케줄링 지원을 받지 않기 때문에, 해당 스레드에 대한 문맥 교환이 일어나지 않는다. 따라서 스핀락은 임계 구역에 짧은 시간 안에 진입할 수 있는 경우에 문맥 교환을 제거할 수 있어 효율적이다. 하지만 만약 스핀락이 오랜 시간을 소요한다면 다른 스레드를 실행하지 못하고 대기하게 되며, 이 경우 비효율적인 결과를 가져온다

 

 

2)Test and Modify(하드웨어적 락):

 

 

 instruction 단위로 cpu 뺏길수도 있어서 생기는 위의 문제를 

하드웨어적으로 instruction이 끝날때마다 flag 바꿔주는 것을 지원하는 방법이다. 

 

Issue->여전히 프로그래머의 실수가 영향을 미친다는 단점을 가지고 있다.

 

 

 

 

3)세마포어: 

 

 

위의 방식들을 추상화시킨 방법이다. 

세마포어 S는 정수값을 가지는 변수이고, P와 V라는 명령으로만 접근할 수 있다. 

즉, 한 프로세스(또는 스레드)에서 세마포어 값을 변경하는 동안 다른 프로세스가 동시에 이 값을 변경해서는 안 된다.

 

 

방법1...스핀락 사용

P(S) { while S <=0; // 아무것도 하지 않음 (반복문)  S--; } 자원 얻음

V(S) { S++; }  자원 반납

 

방법2...슬립락 사용(바쁜대기를 보완하여, cpu와 메모리를 쓰지않는동안 넘겨준다 )

P(S) { S--; if S < 0 // 이 프로세스를 재움 큐에 추가 (block) }  가용자원 없으니 block하는거다. 1편 참고

V(S) { S++; if S <= 0 // 재움 큐로부터 프로세스를 제거 (wakeup) } 되돌려줬는데도 음수란건 누군가가 음수로 만들고 block되있는 상태라는걸 뜻한다. block된  프로세스를 깨운다.

 

Issue->여전히 프로그래머의 실수가 영향을 미친다는 단점을 가지고 있다.

 

 

 

 

 

 

 

 

 

종류: 이진 세마포어(0또는 1만 가질 수 있고 mutex구현을 위해 사용한다), 계수 세마포어(그 외. 다른 프로세스가 접근 못한다는 특성을 이용해서 자원카운팅만 할 때 사용한다)

 

 

 

4)모니터(최종보스)

 

고급 언어(Java)에서 이 기능을 지원하며, 한번에 하나의 프로세스만 모니터에서 활동하도록 보장해준다. 모니터는 안에 공유변수 넣어두고, 공유변수 접근하는 함수들을 내부에 모아둔다.그리고 자체적으로 활동 가능한 함수는 하나만 되도록 만듬.프로세스가 모니터에 들어가고자 할 때 다른 프로세스가 모니터 내부에 있다면 입장 큐에서 기다려야 한다.

 

 

 

Difference?

세마포어는 스핀락이라 자원낭비가 생기거나, 보완된 방식을 사용해도 block 때문에 문맥교환 비용이 증가하는 반면

모니터는 입장 큐에 대기만 하면 되기 때문에 그 비용이 발생하지 않는다. 또한, 락을 거는 것이 아니기 때문에 자원을 더 쓸 수 있어서 효율적이다

 

 

 

 

위에서 나왔던 모든 Issue를 처리한 상태로 동기화한 것을 thread safe라고 한다.

 

 

//자바의 String 관련 동기,비동기도 알아보자

//생산자,공급자 ..배고픈 철학자 등 건넜음

//세마포어,뮤텍스 구현 한번 해보면 좋을듯

+ Recent posts