본문 바로가기
컴퓨터 과학/운영체제

[운영체제] 프로세스와 메모리 구조(7): 프로세스 동기화

by webcodur 2024. 4. 27.
728x90

 

목차

     
    현대 운영 체제는 멀티 프로세싱 환경을 지원하여 여러 프로세스가 동시에 실행될 수 있게 한다. 이러한 환경에서 데이터 무결성을 유지하고 프로세스 간 상호 작용을 조율하기 위해서는 프로세스 동기화 기술이 필수적이다. 본 글에서는 프로세스 동기화의 개념, 필요성, 그리고 주요 동기화 기법들이 폭넓게 다루어진다.
     

    1. 프로세스 동기화

    1.1 프로세스 동기화란 무엇인가

    여러 프로세스가 공유 자원의 일관성을 유지하는 것”
    간단히는 ‘프로세스 수행 시기를 맞추는 것’ 을 일컫고, 정확히는 ‘프로세스 실행 순서를 제어하고 동시에 접근할 수 없는 자원에 하나의 프로세스만 접근하게 하는 것’을 뜻한다. 프로세스는 이를 통해 데이터 일관성을 유지할 수 있다.
     

    1.2 프로세스 동기화 vs 프로세스 스케줄링

    동기화를 더 학습하기 전에 두 개념을 간단히 정리하도록 한다.
     
    <개념 비교>

    • 프로세스 동기화: 여러 프로세스가 공유 자원안전하게 사용하도록 조율하는 것이 목적. 이를 통해 데이터 손상이나 시스템 오류를 방지하고, 원하는 작업 순서를 유지할 수 있다.
    • 프로세스 스케줄링: CPU에 가장 적합한 프로세스선택하여 실행하는 것이 목적. 이를 통해 시스템 성능을 최적화하고, 응답 속도를 향상시킬 수 있다.

    <비유를 통한 이해>

    • 프로세스 동기화: 여러 사람이 동시에 화장실을 사용하려는 상황과 같다. 뮤텍스는 마치 한 번에 한 사람만 화장실에 들어갈 수 있도록 하는 문처럼 작동한다. 세마포어는 화장실 칸이 여러 개 있어서 제한된 수의 사람이 동시에 사용할 수 있다. 조건 변수는 화장실을 사용하고 싶은 사람이 칸이 비어 있을 때까지 기다렸다가 사용하는 사람이 나오면 들어가는 원리로 작동한다.
    • 프로세스 스케줄링: 식당에서 선 손님들을 처리하는 상황과 같다. 선택 알고리즘은 웨이터가 무작위로 손님을 선택하는 방식이고, 라운드 로빈 알고리즘은 웨이터가 손님들을 순서대로 처리하는 방식이다. 우선순위 알고리즘은 배고픈 아이가 있는 가족이나 VIP 손님을 우선적으로 처리하는 방식이다.

    <각 수행 주체>

    • 프로세스 동기화: 프로세스가 주체
      • 여러 프로세스가 공유 자원안전하게 사용하도록 서로 조율한다.
      • 도로 교차로에서 신호등이 여러 차량의 안전한 통행을 위해 조율하는 것과 같다.
      • 비유: 신호등이 위에서 자동으로 작동하지만, 차량들이 신호를 따르는 협력이 필요하다.
    • 프로세스 스케줄링: 운영체제스케줄러가 주체
      • CPU에 가장 적합한 프로세스를 선택하여 실행한다
      • 프로세스 상태, 우선순위, 시스템 전체의 부하 등을 고려하여 스케줄링 알고리즘을 사용한다.
      • 비유: 웨이터는 손님들의 요청을 먼저 듣고 상황에 맞게 판단하여 안내한다.

    1.3 프로세스 동기화의 충돌 억제 원리

    그런데 프로세스 동기화 기술들이 각 프로세스에 들어가 있고 각기 기술이 다른 상황에서 어떻게 똑같이 신호를 분석하고 동작하는 것이 가능한가? 다음은 그에 대한 해결 방법이다.

    1. 공유 메모리 활용: 각 프로세스는 공유 메모리 영역에 자신의 동기화 정보를 저장한다. 신호등 제어 프로세스는 공유 메모리를 읽어 각 프로세스의 동기화 상태를 파악한다. 이를 통해 모든 프로세스의 동기화 상태를 고려하여 신호를 변경할 수 있다.
    2. 메시지 전달 활용: 각 프로세스는 메시지를 사용하여 자신의 동기화 정보를 신호등 제어 프로세스에 전송한다. 신호등 제어 프로세스는 수신된 메시지를 기반으로 각 프로세스의 동기화 상태를 파악한다. 이 정보를 바탕으로 모든 프로세스의 동기화 상태를 고려하여 신호를 변경한다.
    3. 협력 프로토콜 활용: 각 프로세스는 협력 프로토콜을 사용하여 서로의 동기화 상태를 공유한다. 신호등 제어 프로세스는 협력 프로토콜을 통해 모든 프로세스의 동기화 상태를 파악한다. 이를 통해 모든 프로세스의 동기화 상태를 고려하여 신호를 변경한다.
    4. 분산 동기화 기술 활용: 분산 동기화 기술을 사용하여 중앙 제어 없이 프로세스들이 자율적으로 동기화된다. 각 프로세스는 자신의 동기화 정보를 지역 메모리에 저장하고, 이웃 프로세스와 정보를 교환한다. 신호등 제어 프로세스는 지역 메모리에 저장된 동기화 정보를 기반으로 신호를 변경한다.
    5. 하이브리드 방식 활용: 여러 기술을 혼합하여 사용하는 하이브리드 방식을 사용할 수도 있다.

     

    2. 이해를 돕기 위한 용어들

    프로세스 동기화 매커니즘 학습 전 관련된 용어들을 먼저 정리하고 넘어가도록 한다.

    2.1. CSP(Critical Section Problem) 와 Race Condition

    2.1.1 개념

    • Race Condition: 여러 프로세스가 공유 변수에 동시에 접근하고 변경할 때, 실행 순서에 따라 결과가 달라지는 문제. 예를 들어, 두 프로세스가 공유 변수의 값을 1씩 증가시키는 경우, 최종 값이 2가 될 수도 있고 1이 될 수도 있다. 여러 프로세스가 공유 변수에 대한 접근을 제어하지 않고 동시에 변경하려고 할 때 발생한다. 이는 프로그래머가 공유 변수의 동시 접근 가능성을 고려하지 않고 코드를 작성했기 때문에 발생한 것이다.
    • Critical Section Problem: 여러 프로세스가 공유 자원에 동시에 접근하여 예상치 못한 결과를 초래하는 문제. 이는 데이터 손상, 시스템 오류 등을 야기할 수 있다. 공유 자원에 대한 동시 접근이 허용되는 경우 발생한다. 명시적인 프로그래밍 오류로 인해 발생하거나, 운영 체제의 동기화 기능 부족으로 인해 발생할 수 있다.

    2.1.2 영향

    • Critical Section Problem: 심각한 시스템 오류, 데이터 손상, 시스템 충돌 등을 야기할 수 있다.
    • Race Condition: 예상치 못한 결과를 초래하여 프로그램의 정확성을 저하시킬 수 있다. 또한, 데이터 손상이나 시스템 오류로 이어질 수도 있다.

    2.1.3 해결 방법

    • Critical Section Problem: 상호 배제 기술을 사용하여 임계 영역(Critical Section)을 정의하고, 한 번에 하나의 프로세스만 임계 영역에 접근하도록 제어해야 한다. 뮤텍스, 세마포어, 모니터 등 다양한 상호 배제 기술을 사용할 수 있다.
    • Race Condition: 원자성(atomicity)을 보장하는 방법을 사용하여 공유 변수에 대한 접근을 제어해야 한다. 원자성 작업은 하나의 연산으로 실행되며, 다른 프로세스의 간섭을 받지 않는다. 또한, 락(lock)을 사용하여 공유 변수에 대한 접근을 순차화하는 방법도 사용할 수 있다.

    2.1.4 비유

    • Critical Section Problem: 여러 사람이 동시에 화장실을 사용하려고 할 때 발생하는 문제에 비유할 수 있다. 서로 충돌하지 않도록 화장실 문을 하나만 열어놓고, 한 사람이 사용하고 나면 다음 사람이 사용하도록 해야 한다.
    • Race Condition: 여러 사람이 동시에 동일한 버스 정류장에서 버스를 타려고 할 때 발생하는 문제에 비유할 수 있다. 누가 먼저 버스에 탈지 정해지지 않아서 버스에 탄 사람과 못 탄 사람이 발생할 수 있다.

    2.2 데드락(Deadlock)

    데드락은 교착 상태라고도 불리며, 두 개 이상의 프로세스가 서로 자원을 기다리고 있는 상태로 인해 아무것도 진행하지 못하는 상황을 의미한다. A는 수저가 있지만 밥이 없고, B는 밥이 있지만 수저가 없는 상황으로 볼 수 있다. 데드락이 발생하면 시스템이 정상적으로 작동하지 않게 되어 심각한 문제가 발생할 수 있다.
    데드락 발생 조건
    데드락이 발생하기 위해서는 다음과 같은 4가지 조건이 모두 만족되어야 한다.

    1. 상호 배제(Mutual Exclusion): 자원은 한 번에 하나의 프로세스만 사용할 수 있다.
    2. 보유 및 대기(Hold and Wait): 프로세스는 이미 자원을 보유하고 있으며, 다른 자원을 기다리고 있다.
    3. 비선점(Non-preemption): 이미 할당된 자원은 강제로 빼앗길 수 없다.
    4. 순환 대기(Circular Wait): 두 개 이상의 프로세스가 서로 다른 자원을 기다리고 있으며, 순환적인 대기 상태에 놓여 있다.

    2.3 원자적 연산(Atomic Operation)

    원자적 연산(Atomic Operation)은 단일 작업 단위로 실행되는 연산을 의미한다. 이러한 연산은 중단되거나 분할될 수 없으며, 시작되면 다른 스레드나 프로세스의 간섭 없이 완료된다.
    원자적 연산의 주요 특징은 다음과 같다:

    1. 분할 불가능성: 연산이 시작되면 완료될 때까지 중단되거나 다른 연산에 의해 간섭받지 않는다.
    2. 일관성: 연산 수행 전후로 데이터의 일관성이 유지되며, 연산의 결과가 예측 가능하다.
    3. 독립성: 여러 연산이 동시에 수행되더라도 각 연산은 다른 연산의 결과에 영향을 받지 않고 독립적으로 실행된다.

    원자적 연산은 특히 멀티스레딩 환경에서 중요하며, 공유 자원에 대한 접근을 안전하게 관리하고 동기화 문제를 해결하는 데 활용된다. 예를 들어, 공유 변수에 대한 증가 연산(increment)이 원자적으로 수행되면, 여러 스레드가 동시에 해당 변수를 변경하려 해도 데이터 경쟁(race condition)을 방지할 수 있다. 이러한 연산은 compare-and-swap, test-and-set 같은 원자적 명령을 통해 구현된다.
     

    3. 프로세스 동기화 기술들

    3.1 락 기반 동기화 방식

    락 기반 동기화는 스레드 또는 프로세스가 공유 자원에 대한 접근을 제어하기 위해 락(잠금) 메커니즘을 사용하는 방법이다. 이 접근 방식은 동시성을 관리하고 데이터 일관성을 유지하는 데 필수적이다. 다음은 락 기반 동기화의 대표적인 기술들이다:

    3.1.1 뮤텍스 (Mutex)

    ‘락을 가진 단 한명만 접근’
    뮤텍스는 "Mutual Exclusion"의 약자로, 한 번에 하나의 스레드만 특정 자원이나 코드 섹션에 접근할 수 있도록 허용한다. 임계 구역(critical section)이라는 공유 자원에 대한 독점적 접근을 허용하는 방식이다. 뮤텍스는 소유가 가능하며, 락을 소유한 스레드만이 해당 락을 해제할 수 있다. 이는 마치 한 번에 한 사람만 입장할 수 있는 화장실과 같다. 뮤텍스는 데드락 회피에 도움을 줄 수 있지만, 소유자가 락을 제때 해제하지 않으면 다른 스레드들이 무한 대기 상태에 빠질 수 있다.

    3.1.2 스핀락 (Spinlock)

    ‘락을 획득할 때까지 반복 시도’
    스핀락은 스레드가 자원을 획득할 때까지 잠금을 반복적으로 시도하며, CPU를 계속 사용하는 락 기반 동기화 방식이다. 스핀락은 대기하는 동안 스레드가 계속해서 CPU 사이클을 소모하므로, 잠금 대기 시간이 짧은 상황에서 유용하다. 그러나 잠금을 오래 기다려야 하는 상황에서는 CPU 자원을 낭비할 수 있으므로, 사용 상황을 신중히 고려해야 한다.

    3.1.3 리더-라이터 락 (Reader-Writer Locks)

    ‘읽기와 쓰기 작업 분리’
    리더-라이터 락은 읽기 작업과 쓰기 작업을 구분하여 처리하는 동기화 방식이다. 여러 스레드가 동시에 읽기 작업을 수행할 수 있도록 허용하지만, 쓰기 작업을 수행하는 스레드는 독점적인 접근 권한을 갖는다. 이 방식은 데이터를 자주 읽지만, 수정은 드물게 발생하는 경우에 효과적이다. 리더-라이터 락은 읽기 작업 중인 상황에서 쓰기 작업이 발생하면, 새로운 읽기 작업을 잠시 대기시키고 쓰기 작업을 우선 처리함으로써 데이터 일관성을 유지한다.

    3.1.4 synchronized

    ‘객체 또는 메소드에 대한 동시 접근 제한’
    **synchronized**는 자바에서 사용되는 동기화 키워드로, 특정 객체의 메소드나 코드 블록에 대한 동시 접근을 제한한다. 이 기법을 사용할 때, 스레드는 객체의 락을 획득해야 해당 부분의 코드를 실행할 수 있다. 락을 보유한 스레드만이 객체에 접근할 수 있으며, 다른 스레드들은 락이 해제될 때까지 대기해야 한다. 이는 마치 한 번에 한 사람만 이용할 수 있는 개인 사무실과 유사하다. **synchronized**는 데드락 위험을 내포하고 있으며, 잘못 사용할 경우 시스템의 병목 현상을 유발할 수 있다.
     
     

    3.2 락-프리 동기화 방식

    락-프리 동기화는 전통적인 락 기반 방식을 사용하지 않고, 원자적 연산을 통해 여러 스레드가 공유 자원을 안전하게 접근할 수 있도록 하는 기법이다. 이 접근법은 락 경합(lock contention), 데드락(deadlock), 그리고 락 기반 동기화의 기타 단점들을 회피하고자 할 때 사용된다. 다음은 락-프리 동기화의 대표적인 기술들이다:

    3.2.1 세마포어 (Semaphore)

    ‘접근 가능 개수 제한’
    세마포어는 동시에 여러 스레드가 자원에 접근할 수 있도록 허용하는 메커니즘으로, 내부적으로 카운터라는 값을 유지한다. 이 카운터는 동시에 접근할 수 있는 최대 스레드 수를 나타내며, 스레드가 세마포어를 획득하면 카운터가 감소하고, 세마포어를 방출하면 카운터가 증가한다. 카운터가 0이 되면 추가 스레드는 대기 상태에 들어가며, 이는 P(감소) 연산과 V(증가) 연산을 통해 자원의 접근을 제어한다.

    3.2.2 티켓 락 (Ticket Lock)

    ‘순차적 접근 보장’
    티켓 락은 스레드가 서비스를 받기 위해 티켓을 뽑고, 티켓 번호 순서대로 임계 구역에 접근할 수 있도록 하는 방식이다. 이 방법은 각 스레드가 공정하게 접근 권한을 얻을 수 있도록 순차적으로 접근을 관리하며, 락 경합을 줄이는 효과가 있다. 티켓 락은 세마포어와 유사하지만, 접근 순서를 보다 엄격하게 제어하는 특징을 갖는다.

    3.2.3 배리어 (Barrier)

    ‘동기화 지점 도달 대기’
    배리어는 모든 스레드가 특정 지점, 즉 배리어에 도달할 때까지 서로를 대기시키는 동기화 메커니즘이다. 이는 특히 병렬 프로그래밍에서 유용하며, 모든 스레드가 동시에 다음 단계로 진행해야 할 때 사용된다. 배리어를 통해 스레드들은 모두가 동일한 처리 상태에 있음을 보장받고, 다음 연산이 시작되기 전에 필요한 모든 데이터 처리가 완료됨을 확인할 수 있다.

    3.2.4 비차단 자료구조 (Non-blocking Data Structures)

    ‘락-프리 자료 구조’
    비차단 자료구조는 다중 스레드 환경에서 공유 데이터에 대한 접근을 락 없이 관리하는 방식이다. 이러한 구조들은 원자적 연산을 활용하여 데이터의 일관성을 유지하면서, 스레드 간 차단을 방지한다. 비차단 자료구조는 시스템의 전반적인 반응성과 확장성을 향상시키며, 데드락의 위험 없이 동작한다.
    이 자료구조의 주요 이점은 특히 고성능 멀티코어 프로세서에서 나타난다. 예를 들어, 비차단 큐는 스레드가 큐에 항목을 추가, 제거할 때 다른 스레드의 작업에 의해 차단되지 않는다. 각 스레드는 **compare-and-swap**과 같은 원자적 연산을 사용하여 큐의 상태를 안전하게 변경할 수 있다.
    이 구조는 실시간 시스템, 금융 거래 시스템 등에서 필수적인 요소로 사용된다. 비차단 자료구조는 동시성을 극대화하고, 시스템의 성능과 안정성을 보장하는 데 중요한 역할을 한다.

    3.2.4 CAS (Compare And Swap)

    ‘조건이 충족될 때만 값 변경’
    CAS는 원자적 연산을 사용하여 특정 메모리 위치의 값을 비교한 후, 예상한 값이 맞을 경우에만 새로운 값으로 업데이트하는 기법이다. 이 연산은 락을 사용하지 않으므로, 여러 스레드가 동시에 접근하더라도 시스템의 성능 저하 없이 공유 자원의 일관성을 유지할 수 있다. CAS는 마치 대기열 없이 여러 사람이 동시에 티켓 기계를 사용하는 것과 비슷하다. 그러나 예상 값이 계속 변경될 경우, CAS는 성공하기 어렵고, 이로 인해 추가적인 처리가 필요할 수 있다.
     

    3.3 조건 동기화

    조건 동기화는 스레드가 특정 조건을 만족할 때까지 대기하게 하고, 조건이 만족될 때 실행을 계속하도록 하는 동기화 기법이다. 이 방식은 스레드가 불필요한 자원 점유를 피하면서 특정 상황이 발생하기를 기다리게 한다. 다음은 조건 동기화의 대표적인 기술들이다:

    3.3.1 모니터 (Monitor)

    ‘뮤텍스 + 조건변수’
    모니터는 뮤텍스와 조건 변수를 결합하여 사용하는 고수준의 동기화 기법이다. 모니터 내에서 스레드는 특정 코드 섹션을 독점적으로 실행할 수 있으며, 조건 변수를 사용해 특정 조건이 충족될 때까지 대기하게 할 수 있다. 이 기법은 특히 복잡한 동기화 조건이 필요한 상황에서 유용하며, 스레드 간의 상호작용을 명확하고 효율적으로 관리할 수 있다.

    3.3.2 조건 변수 (Condition Variable)

    ‘특정 조건 충족 대기’
    조건 변수는 스레드가 특정 조건이 충족될 때까지 대기하도록 하고, 조건이 충족되면 대기 중인 스레드를 깨우는 메커니즘을 제공한다. 이 기술은 보통 뮤텍스와 함께 사용되어, 조건의 변화가 발생했을 때 안전하게 자원 상태를 확인하고 접근할 수 있게 한다. 조건 변수는 대기 중인 스레드를 효율적으로 관리할 수 있도록 도와준다.
     
     

    3.4 소프트웨어 기반 알고리즘

    소프트웨어 기반 알고리즘은 하드웨어의 직접적인 지원 없이, 소프트웨어 로직을 통해 동기화와 상호 배제를 달성하는 방법이다. 이러한 알고리즘들은 다양한 상황에서 유연하고 효율적인 동기화를 제공할 수 있다. 다음은 소프트웨어 기반 알고리즘의 대표적인 기술들이다:

    3.4.1 Peterson's Algorithm

    ‘두 스레드의 상호 배제 보장’
    Peterson's Algorithm은 두 개의 스레드가 상호 배제를 보장하면서 임계 구역에 접근할 수 있도록 하는 소프트웨어 기반 알고리즘이다. 이 알고리즘은 두 스레드 간의 경쟁을 해결하기 위해 간단한 변수(플래그와 턴)를 사용하여, 어느 한 쪽이 임계 구역을 사용 중일 때 다른 한 쪽이 대기하도록 한다. 이는 매우 간단하면서도 효과적인 상호 배제 방식을 제공한다.

    3.4.2 Software Transactional Memory (STM)

    ‘트랜잭션을 통한 메모리 접근’
    Software Transactional Memory는 데이터베이스의 트랜잭션처럼 메모리 트랜잭션을 소프트웨어적으로 구현하여, 복잡한 동기화 문제를 해결한다. STM은 여러 스레드가 동시에 데이터를 읽거나 쓸 때 발생할 수 있는 충돌을 관리하고, 모든 변경 사항을 한 번에 원자적으로 적용하도록 설계되었다. 이 방식은 코드의 간결성을 유지하면서도 강력한 동시성 제어를 가능하게 한다.

    3.4.3 Read-Copy-Update (RCU)

    ‘읽기 중심의 환경에서의 동기화’
    Read-Copy-Update는 읽기 작업이 빈번하게 발생하고 쓰기 작업은 비교적 드물 때 효과적인 동기화 메커니즘으로, 쓰기 작업시 복사본을 만들어 업데이트 후 읽기 작업자에게 전환하는 방식이다. RCU는 읽기 작업의 성능을 저하시키지 않으면서 쓰기 작업을 안전하게 수행할 수 있도록 한다. 이 기술은 높은 동시성을 필요로 하는 시스템에서 특히 유용하다.

    3.4.4 volatile

    ‘메모리 가시성 보장’
    volatile 키워드는 변수가 다수의 스레드에 의해 공유될 때 메모리 가시성을 보장한다. 어원적으로, volatile은 라틴어 ‘volatilis’에서 유래되었으며, ‘날아다니는’, ‘변덕스러운’, 또는 ‘변경 가능한’을 의미한다. 이는 volatile 변수가 예측할 수 없는 방식으로 변경될 수 있음을 나타낸다. 이러한 변수는 항상 메인 메모리에서 읽히고 쓰여지며, 컴파일러 최적화가 이루어지지 않아 변수 값의 최신 상태가 모든 스레드에 의해 즉시 감지된다. 이는 마치 공개된 게시판에서 각자의 메모를 확인하는 것과 유사하다. 하지만, volatile은 복합적인 동기화 작업에는 적합하지 않으며, 주로 간단한 플래그 값의 동기화에 적합하다.
     

    3.5 고급 동기화 메커니즘

    고급 동기화 메커니즘은 복잡한 시스템 환경에서 필요한 특수한 요구 사항을 충족시키기 위해 설계된 동기화 기술들을 포함한다. 이들은 기존의 동기화 방법보다 더욱 복잡한 상황에서의 데이터 일관성과 스레드 간의 효율적인 작업 조정을 가능하게 한다. 다음은 고급 동기화 메커니즘의 대표적인 기술들이다:

    3.5.1 Message Passing

    ‘프로세스 간의 직접적인 메시지 교환을 통한 동기화’
    Message Passing은 프로세스나 스레드가 메시지를 통해 데이터를 주고받으며, 메시지 자체가 동기화 메커니즘으로 작용한다. 이 방식은 데이터의 공유 없이 각 스레드 또는 프로세스가 독립적으로 작동하면서도 필요한 정보를 교환할 수 있도록 한다. 메시지 패싱은 복잡한 시스템에서 동기화 문제를 회피하는 데 유용하며, 특히 분산 시스템에서 널리 사용된다.

    3.5.2 Priority Inheritance

    ‘우선순위 역전 문제의 해결’
    Priority Inheritance는 낮은 우선순위의 스레드가 높은 우선순위의 스레드를 블록할 때 발생하는 우선순위 역전 문제를 해결하기 위한 방법이다. 이 기술은 낮은 우선순위 스레드가 높은 우선순위 스레드에 의해 차단된 자원을 사용할 때, 자동으로 높은 우선순위를 상속받아 실행되게 함으로써 시스템의 반응 시간과 신뢰성을 개선한다.

    3.5.3 Read-Copy-Update (RCU)

    ‘읽기 중심의 환경에서의 효율적인 동기화’
    Read-Copy-Update는 읽기 작업이 빈번하게 발생하고, 쓰기 작업은 비교적 드물 때 효과적인 동기화 메커니즘으로, 쓰기 작업시 복사본을 만들어 업데이트 후 읽기 작업자에게 전환하는 방식이다. RCU는 읽기 작업의 성능을 저하시키지 않으면서 쓰기 작업을 안전하게 수행할 수 있도록 한다. 이 기술은 높은 동시성을 필요로 하는 시스템에서 특히 유용하다.
     
     

    3.6 우선순위 기반 동기화

    우선순위 기반 동기화는 스레드 또는 프로세스의 실행 우선순위를 관리하여 동기화 문제를 해결하는 기술들을 포함한다. 이러한 기술들은 주로 실시간 시스템에서 우선순위 역전 문제를 방지하고 시스템의 반응성과 신뢰성을 개선하는 데 사용된다. 대표적인 기술로는 다음과 같은 것들이 있다:

    3.6.1 우선순위 상속 기법 (Priority Inheritance)

    ‘우선순위 역전 문제 해결’
    우선순위 상속 기법 높은 우선순위의 스레드가 낮은 우선순위의 스레드에 의해 블록되는 문제, 즉 우선순위 역전을 해결하기 위한 기법이다. 이 메커니즘을 통해, 높은 우선순위의 스레드가 대기 중일 때, 낮은 우선순위의 스레드는 자동적으로 높은 우선순위를 상속받아 실행된다. 이로 인해 시스템의 반응 시간과 신뢰성이 향상될 수 있다.

    3.6.2 우선순위 상한 기법(Priority Ceiling Protocol)

    ‘리소스 별 최고 우선순위 할당’
    우선순위 상한 기법에서는 각 리소스(락)에 상한 우선순위를 설정한다. 스레드가 해당 리소스를 점유하면, 그 스레드의 우선순위는 자동적으로 해당 리소스의 상한 우선순위로 상승한다. 이로써, 해당 리소스를 점유하는 동안 스레드는 다른 낮은 우선순위의 스레드에 의해 차단되지 않도록 보호받게 된다. 또한, 한 번에 하나의 스레드만이 상한 우선순위를 갖는 리소스를 사용할 수 있어서 데드락 가능성을 줄일 수 있다.
     
     

    3.7 비동기 및 병렬 프로그래밍 동기화

    3.7.1 퓨처스와 프라미스 (Futures and Promises)

    ‘비동기 작업의 결과 관리’
    퓨처스와 프라미스는 비동기 연산을 위한 프로그래밍 추상화로, 연산이 완료될 때까지 코드의 다른 부분이 진행될 수 있도록 한다. 퓨처(Future)는 아직 완료되지 않은 연산의 결과를 대표하며, 프라미스(Promise)는 그 결과를 나중에 제공할 책임을 가진 객체이다. 이 메커니즘을 통해 개발자는 복잡한 비동기 로직을 보다 쉽게 관리할 수 있으며, 연산이 완료된 후에 결과를 처리할 콜백 함수를 등록할 수 있다. 이는 특히 웹 서비스나 네트워크 통신, 대규모 데이터 처리와 같은 환경에서 효율적인 리소스 관리를 가능하게 한다.

    3.7.2 래치와 플립-플롭 (Latches and Flip-flops)

    ‘상태 유지 동기화’
    래치와 플립-플롭은 주로 디지털 회로 설계에서 사용되는 기본적인 저장 요소로, 이들은 입력된 신호에 따라 두 상태(1 또는 0) 중 하나를 유지한다. 래치는 입력 신호가 주어지는 동안만 상태를 변경할 수 있지만, 플립-플롭은 특정 클록 신호의 엣지에 반응하여 상태가 변경된다. 이러한 속성 때문에 래치와 플립-플롭은 동기화의 중요한 역할을 하며, 복잡한 동기화 문제를 해결하는데 사용된다. 예를 들어, 멀티코어 프로세서에서 여러 프로세스 간에 일관된 상태를 유지하는 데 필수적이다.

    3.7.3 비동기 입출력 (Asynchronous I/O)

    ‘비차단 입출력 처리’
    비동기 입출력(AIO)은 입출력 작업을 시작한 후, 그 작업이 완료되기를 기다리지 않고 즉시 다음 코드 실행을 계속할 수 있게 한다. 이 기술은 특히 데이터베이스 액세스, 파일 시스템 작업, 네트워크 통신 등에서 유용하며, 시스템의 전반적인 처리량과 반응성을 크게 향상시킨다. AIO를 사용함으로써 애플리케이션은 I/O 대기 시간 동안 CPU가 다른 작업을 수행할 수 있어 자원 사용의 효율성이 증가한다.

    3.7.4 코루틴 (Coroutines)

    ‘협력적 멀티태스킹’
    코루틴은 비동기 프로그래밍을 위한 강력한 도구로, 하나의 실행 흐름이 중단점에서 일시 중지되고 다른 실행 흐름으로 제어를 양도할 수 있게 한다. 이러한 협력적 멀티태스킹은 개별 코루틴이 자체 실행을 중단하고 복원하는 능력을 갖추고 있어, 복잡한 비동기 로직을 효과적으로 관리할 수 있다. 코루틴은 특히 사용자 인터페이스, 게임 개발, 서버 사이드 애플리케이션에서 동시에 여러 작업을 수행할 필요가 있을 때 유용하다.