Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- KT포트포워딩
- 웹개발기초
- 운영체제
- 코드트리
- 이것이자바다
- 이것이자바다확인문제
- 백준스택
- 코딩테스트실력진단
- 2019카카오코테
- BOJ1655
- 합성곱연산
- 백준
- 코테
- 백준괄호
- 딥러닝
- 윤곽선검출
- 컴퓨터비전
- 카카오코테
- 백준가운데를말해요
- java
- 백준10828
- 스파르타코딩클럽
- 백준9012
- 백준온라인저지
- BOJ
- 가운데를말해요
- 백준평범한배낭
- 확인문제
- 냅색알고리즘
- 이것이자바다9장
Archives
- Today
- Total
코딩하는 락커
11. 프로세스 동기화: Chapter 6. Synchronization Tools (Part 1) 본문
6.1 배경Background
- 프로세스가 병행concurrent 또는 병렬parallel로 실행될 때 여러 프로세스가 공유하는 데이터의 무결성에 문제가 생길 수 있음
- 생산자-소비자 문제
- 생산자: 버퍼에 새 항목을 초기화 할 때 마다 0으로 초기화 되어 있는 count 값을 1 증가함
- 소비자: 버퍼에서 한 항목을 꺼낼 때마다 0으로 초기화 되어 있는 count값을 -1 감소함


- 병행으로 수행할 경우 count의 값은 4나 5나 6이 됨
- 실습 예제1 코드
#include <stdio.h>
#include <pthread.h>
int sum = 0;
void *run(void * param){
int i;
for (i=0; i<10000; i++){
sum++;
}
pthread_exit(0);
}
int main(){
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, run, NULL);
pthread_create(&tid2, NULL, run, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("%d\n", sum);
}

- 실습 예제 2 코드
#include <stdio.h>
#include <pthread.h>
int sum = 0;
void *run1(void *param){
int i;
for (i=0; i<10000; i++){
sum++;
}
pthread_exit(0);
}
void *run2(void *param){
int i;
for (i=0; i<10000; i++){
sum--;
}
pthread_exit(0);
}
int main(){
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, run1, NULL);
pthread_create(&tid2, NULL, run2, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("%d\n", sum);
}

- 원인
- count ++의 기계어 구현
- register1 = count
- register1 = register1 +1
- count = register1
- count --의 기계어 구현
- register2 = count
- register2 = register2 +1
- count =
- register1, register2는 한 CPU만 접근할 수 있는 레지스터 중 하나임
- register1, register2가 동일하 물리적 레지스터더라도 이 레지스터의 내용은 인터럽트 처리기에 의해 메모리에 보관되었다가 다시 적재됨
- 따라서 아래 그림과 같은 순서를 가질 수 있음
- count ++의 기계어 구현

- 이러한 부정확한 상태에 도달하는 것은 두 개의 프로세스가 동시에 변수 count를 조작하도록 허용했기 때문임
- 경쟁 상황race condition: 동시에 여러 개의 프로세스가 동일한 자료를 접근하여 조작하고, 그 실행 결과가 접근이 발생한 특정 순서에 의존하는 상황
- 한 순간에 한 프로세스만이 변수 count를 조작하도록 보장하기 위해 프로세스들이 동기화synchronized되도록 할 필요가 있음
- Race Condition Java 예제 코드
package com.os_study.ch04;
class RunnalbeTwo implements Runnable{
static int count = 0;
@Override
public void run() {
for(int i=0; i<10000; i++){
count++;
}
}
}
public class RaceCondition2 {
public static void main(String[] args) throws Exception{
RunnalbeTwo run1 = new RunnalbeTwo();
RunnalbeTwo run2 = new RunnalbeTwo();
Thread t1 = new Thread(run1);
Thread t2 = new Thread(run2);
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println("Result: " + RunnalbeTwo.count);
}
}


6.2 임계구역 문제 The Critical Section Problem
- 임계구역critical section: 하나 이상의 다른 프로세스와 공유하는 데이터를 접근하고 갱신하는 코드 영역
- 한 프로세스가 자신의 임계구역에서 수행하는 동안 다른 프로세스들은 그들의 임계구역에 들어올 수 없음
- 임계구역 문제
- 프로세스들이 데이터를 협력적으로 공유하기 위하여 자신들의 활동을 동기화할 때 사용할 수 있는 프로토콜을 설계하는 것
- 진입 구역entry section: 임계구역으로 진입하기 위해 진입 허가를 요청하는 부분
- 퇴출 구역exit section: 임계구역 뒤에 나오는 부분, 후처리를 해줌
- 나머지 구역remainder section: 코드의 나머지 부분을 총칭
- 임계구역 문제에 대한 해결안의 3가지 요구조건
- 상호 배제mutual exclusion: 프로세스가 Pi가 자기의 임계구역에서 실행된다면 다른 프로세스들은 그들 자신의 임계구역에서 실행될 수 없음
- 진행progress: 자신의 임계구역에서 실행되는 프로세스가 없고 그들 자신의 임계구역으로 진입하려고 하는 프로세스들이 있다면 다음에 누가 임계구역으로 진입할 수 있는지를 결정하는지에 대한 선택은 무한정 연기될 수 없음
- 한정된 대기bounded waiting: 프로세스가 자기의 임계구역에 진입하려는 요청을 한 후부터 그 요청이 허용될 때 까지 다른 프로세스들이 그들 자신의 임계구역에 진입하도록 허용되는 회수에 한계가 있어야 함
- 많은 커널 모드 프로세스들이 동시에 운영체제 안에서 활성화될 수 있으므로 운영체제를 구현하는 코드(커널 코드)는 경쟁 조건이 발생하기 쉬움

- 위 그림은 P0, P1 두 프로세스가 fork() 시스템 콜을 사용하여 자식 프로세스를 생성하는 예시를 나타냄
- fork()는 새로 생성된 프로세스의 프로세스 식별자를 부모 프로세스로 변환함
- 이 예시에서 커널변수 next_available_pid는 다음 사용 가능한 프로세스 식별자의 값을 나타내며 경쟁 조건에 있음
- 상호 배제가 제공되지 않으면 동일한 프로세스 식별자 번호가 두 개의 다른 프로세스에 배정될 수 있음
- 단일 코어 환경에서는 공유 변수를 수정하는 동인 인터럽트가 발생하는 것을 막으면 임계구역 문제를 해결할 수 있음
- 멀티 코어 환경에서 실현할 수 없음
- 메시지가 모든 프로세서에 전달되므로 인터럽트를 비활성화 하면 시간이 많이 걸림
- 또한 이 메시지 전달은 각 임계구역으로의 진입을 지연시키고 시스템 효율성을 떨어뜨림
- 멀티 코어 환경에서 실현할 수 없음
- 운영체제에서 임계구역 문제를 다루기 위한 2가지 접근법
- 선점형 커널
- 프로세스가 커널 모드에서 수행되는 동안 선점되는 것을 허용
- 커널 모든 프로세스가 대기 중인 프로세스에 처리기를 양도하기 전에 오랫동안 실행할 위험이 적기
때문에 응답이 더 민첩하므로 선점형 커널을 선호함
- 비선점형 커널
- 프로세스가 커널 모드에서 수행되는 동안 선점되는 것을 허용하지 않음
- 한 순간에 커널 안에서 실행중인 프로세스는 하나밖에 없으므로 경쟁 조건을 염려할 필요 없음
- 선점형 커널
'📀 운영체제' 카테고리의 다른 글
13. 뮤텍스와 세마포어: Chapter 6. Synchronization Tools (Part 3) (0) | 2022.06.13 |
---|---|
12. 동기화 문제의 해결책: Chapter 6. Synchronization Tools (Part 2) (0) | 2022.06.07 |
10. 스케줄링 알고리즘: Chapter 5. CPU Scheduling (Part 2) (0) | 2022.06.06 |
09. CPU 스케줄링: Chapter 5. CPU Scheduling (Part 1) (0) | 2022.05.31 |
07 ~ 08. 쓰레드의 이해: Chapter 4. Thread & Concurrency (Part 1 ~ Part 2) (0) | 2022.05.30 |
Comments