여러개의 프로세스가 하나의 자원에 동시에 접근하게되면 일관성을 유지할 수 없다.
이렇게 공유되는 데이터에 접근하는 코드를 critical section 이라고 한다.
이 문제점을 해결하기위해 프로세스 동기화가 필요하다.
해결 방법 : critical section에 하나의 프로세스만 접근 가능하도록
1,2,3 과정을 반복
하지만 P1이 turn 1 을 확인했지만 critical section 을 점유하지 않는다면 critical section을 비어있게되는 문제가 발생
1,2,3,4 반복
하지만 데드락 발생 가능 : 모든 프로세스가 동시에 critical section 에 접근하려 한다면 서로 못들어가는 상황 발생(둘다 들어가고자 하는 의지가 있지만 다른 프로세스의 flag 가 true 라면 들어가지 못하기때문)
프로세스가 들어가고자 하는 의지가 있는 프로세스를 확인하고 turn값이 무조건 하나는 보장되기때문에 critical section이 비어있을 일도 없고 deadlock 현상도 없다.
하지만 Busy Waiting 현상 발생 : 프로세스가 일을 다하고 대기를 하는 시간에도 critical section를 점유해야한다.(P0가 일이 끝나고 P1이 점유하고 싶을때까지 critical section를 점유한다)
deadlock이 발생할 수 없는 이유는 lock은 원자성을 지키기때문에 반드시 하나에만 lock을 걸어줄 수 있다. 동시에 접근해도 하나에만 락을 걸음
세마포어란, 멀티 프로그래밍 환경에서 하나의 자원에 대한 접근을 제어하는 방법
- binary semaphores(mutex)
- 하나의 자원을 동기화 시키기 위한 방법
- 단독으로 실행되도록 하는 기술
ex) 화장실 한칸- semaphores
- 여러개의 자원을 동기화시켜주기 위한 방법(counting)
ex) 주차장
설명을 위해 단어 설명
P : wait function(진입을 확인하기위한 코드)
V : signal function(점유가 끝났을 때 쓰는 코드)//initial S=1 P(S): S--; while(S<=) wait; V(S); S++;
여기서 S는 접근할 수 있는 resource의 수를 의미합니다.
즉 resource에 접근한다면 S-- 해서 접근 가능한 자원을 줄이고 점유가 끝났을때는 S++하여 접근 가능한 자원을 늘려줍니다.
또한, S==0일때에는 접근할 수 없습니다.
때문에 S가 양수의 경우는 사용할 자원의 개수를 의미하고, 음수의 경우에는 대기하고있는 프로세스의 수를 의미합니다.
물론 Peterson Algorithm을 사용해서 구현할 수 있지만 Busy Waiting 문제가 발생할 수 있습니다.
추가적으로 busy waiting 문제를 Spin Lock 이라고 합니다.
이에 대한 해결책으로 PCB를 뒤에 매달고서 실행되고 있는 프로세스가 끝나면 다음 프로세스를 깨우는 방식을 사용합니다.
매달려서 대기하고있는 프로세스들의 thread는 sleep에 들어가 자원을 소모하지 않습니다.
하지만! block/wakeup 은 잠들어 있는 애들을 깨운다 즉, running의 상태를 -> waiting으로, waiting -> ready 로 변경해주는 context-switching 비용이 발생하고 spinLock의 경우 context-switching 비용이 발생하지 않습니다.( 상태를 변경하는 것이 아닌 접근을 못하고 있는 것이기 때문 )때문에, critical section가 짧아서 프로세스 교체가 자주 발생하는 경우라면 busy waiting 기법이 더 효과적일 수 있습니다.
공유 데이터가 버퍼(배열)에 있고 이 자원을 여러 스레드가 공유하는 상황입니다. 이
이 데이터에 접근할 수 있는 객체를 크게 두가지로 나눈다.
Producer는 비어있는 버퍼의 개수를 확인하고(1 이상이어야함) 자원을 사용한 후 pointer가 다음 buffer를 가리키게 한 후 차있는 버퍼(full)의 값을 1증가한다.
Consumer는 차있는 버퍼의 개수(full)을 확인하고 자원을 사용한 후 empty 를 1 증가한다.
작업을 수행하던 도중 interrupt가 발생해서 공유 자원이 다른 프로세스에게 넘어 갔다면 데이터가 유실될 수 있기 때문에 각각의 자원에 접근할때에는 lock을 걸어준다.
mutex를 적용했을때의 차이가 무엇일까?
semaphore의 차이는 경쟁하는 것이 2개이나 그 이상이냐 아닌가?
DB와 같은 공유 데이터 세트에 대한 읽기 및 쓰기 작업과 관련한 문제입니다.
읽기 작업 : 여러 프로세스가 동시에 읽기 작업 수행이 가능합니다.
쓰기 작업 : 한번에 한 프로세스만 쓰기 작업 수행이 가능합니다.
이 두 작업을 조정하기위해 동기화가 필요합니다.
- 두 작업에게 우선순위를 부여하여서 문제를 해결할 수 있습니다.
- 하지만 이렇게 하게된다면 우선순위가 낮은 작업이 기하현상(stavation)에 빠질 수 있기 때문에 공정성을 보장하기 위한 작업이 필요합니다.
- starvation을 방지하기위한 공정성을 제공(일정 시간까지 도착한 reader만 사용가능하도록)
여러명이 철학자들이 생각하며 식사하는 방식에서 발생하는 문제이다.
1. 각각의 철학자들의 양쪽에 있는 젓가락을 이용해서 식사하고, 식사를 마치면 젓가락을 내려놓고 생각한다.
2. 양쪽의 두개의 젓가락을 들어야만 식사가 가능하고, 한 번에 하나의 젓가락만 잡을 수 있다.
3. 옆 사람이 식사 중이면 젓가락을 잡는 것을 대기한다.
동시에 식사를 진행하게 되면 모두 왼쪽 포크를 쥐고 오른쪽 포크를 잡을 수 있을때까지 대기해야하는 교착 상태가 발생한다.
Mutex를 추상화된 데이터로 만들어서 제공합니다. 때문에, 개발자가 직접 코드를 작성할 필요가 없습니다.
모니터(Monitor)는 동기화와 상호 배제를 위한 고수준 추상화 도구로, 여러 스레드가 공유 자원에 안전하게 접근할 수 있도록 도와줍니다.
ex) 도서관(같은 책은 한사람만 읽을 수 있도록 -> 변수를 사용해서 관리)
mutex와 semaphore와 같이 공유 자원 접근 제어를 제공하고, 추상화하여 프로그래밍 언어 수준에서 제공합니다. 또한, 개발자가 코드를 직접 작성할 필요가 없다는 장점이 있습니다.