티스토리 뷰

반응형

싱글코어가 아니라 멀티코어라면, 어떻게 동기화가 이뤄질까요?

  싱글코어 멀티코어
공통점 Lock(한 번에 하나의 쓰레드만이 접근할 수 있도록 공유 자원을 잠그는 역할) 사용
-> 여러 개의 쓰레드가 동시에 접근하는 경우에 발생할 수 있는 데이터 불일치 문제를 방지
차이점   캐시 일관성 유지 필요
   -> 캐시 프로토콜 사용
특징   - 락 없는 동기화 기법을 사용하는 것이 더욱 효율적인 경우가 있음
- 멀티코어에서 락은 하드웨어적으로 구현되는 것이 보편적

ex.원자적 연산(atomic operation),
    메모리 배리어(memory barrier)

 

 

원자적 연산(Atomic Operation)

여러 개의 쓰레드/프로세스에서 동시에 공유 변수에 접근할 때,  해당 변수를 수정하는 연산을 원자적으로 처리
즉,하나의 연산이 실행되는 도중에는 다른 연산이 해당 변수에 접근하지 못하도록 보호해주는 것
ex.
1.변수 x에 대해 두 개의 스레드 A와 B가 동시에 접근
2. A가 x 값을 증가시키는 도중 B는 해당 변수에 접근할 수 없도록 막아줌

 


메모리 배리어(Memory Barrier)

CPU의 명령어 실행 순서를 제어하는 기술로 메모리 배리어는 캐시와 메인 메모리 간의 데이터를 동기화시키는 역할을 함
이를 통해 캐시와 메인 메모리 간의 일관성을 유지하고, 동시성 문제를 해결할 수 있다.

1. 프로세서는 메인 메모리에서 데이터를 읽어와서 캐시(Cache)라는 중간 저장장치에 저장
   (프로세서가 데이터를 더 빠르게 읽고 쓰기 위해)
2. 이렇게 중간 저장장치인 캐시에 저장된 데이터는 메인 메모리와 일치하지 않을 수 있음
    (특히 여러 개의 코어에서 동시에 메모리를 읽고 쓰는 경우 발생)
     1. 코어1에서 메모리의 데이터를 읽어와 캐시에 저장
     2. 코어2에서 동일한 메모리의 데이터를 변경
     3. 다시 메인 메모리에 저장
     4.코어1의 캐시에는 변경된 데이터가 반영되지 않은 채로 남아 있을 수 있음
3. 메모리 배리어는 이러한 캐시와 메인 메모리의 일관성을 유지하기 위해 사용
=> 메모리 배리어를 사용시 코어가 메모리에 대한 연산을 완료하기 전, 다른 코어가 동일한 메모리에 접근하는 것을 방지

* 메모리 베리어 종류
Load Barrier: 메모리에서 데이터를 읽어오는 명령어 다음에 실행되는 명령어들을 지연시킵니다. 이는 데이터 읽기가 완료되기 전에 실행된 명령어로부터 발생하는 문제를 해결합니다.
Store Barrier: 메모리에 데이터를 쓰는 명령어 이전에 실행되는 명령어들을 지연시킵니다. 이는 데이터 쓰기가 완료되기 전에 실행된 명령어로부터 발생하는 문제를 해결합니다.


메모리 배리어는 원자적 연산과 함께 사용되어, 원자적 연산이 제대로 동작하도록 보장합니다. 즉, 메모리 배리어가 없다면 원자적 연산이 제대로 작동하지 않을 수 있습니다.

 

 

 

*왜 메모리 배리어가 없다면 원자적 연산이 제대로 작동하지 않을 수 있을까?

메모리 배리어가 없으면, 쓰레드나 프로세스 간에 변수 접근 순서가 보장되지 않을 수 있습니다. 
이 경우, A 쓰레드가 X 변수를 변경하는 동안 B 쓰레드가 값을 읽고 계산을 수행하면서 원자적으로 처리되지 않게 됩니다.

따라서, 메모리 배리어를 사용하면 쓰레드나 프로세스 간의 변수 접근 순서를 제어할 수 있기 때문에, 
원자적 연산이 제대로 동작하도록 보장할 수 있습니다. 원자적 연산을 사용하는 경우 메모리 배리어를 함께 사용하여 안전하게 처리하는 것이 좋습니다.

*CPU의 명령어 실행 순서를 제어하는 이유?

  1. 명령어 실행 순서를 제어하면, 프로그램의 동작을 보다 정확하게 제어/안정성 보장할 수 있다. 
    예를 들어, 멀티스레딩(Multithreading) 프로그램에서 여러 스레드가 동시에 동작할 때, 명령어 실행 순서를 제어시 데이터 경쟁(Data Race)이 발생하지 않음

명령어 실행 순서를 제어하면, 프로그램의 성능을 개선할 수 있다. 
예를 들어, 명령어 실행 순서를 최적화하면 캐시(Cache) 미스(Cache Miss)를 줄일 수 있습니다. 이는 프로그램의 실행 속도를 높일 수 있다.

* 명령어 실행 순서를 최적화하면 캐시 미스(Cache Miss)를 줄일 수 있는 이유?

지역성 : 최적화된 명령어 실행 순서를 사용하면 CPU가 참조하는 데이터와 명령어들이 캐시에 미리 저장되어 있을 가능성이 높아지므로 캐시 미스(Cache Miss)가 발생할 확률이 줄어든다.

 

멀티코어에서 락을 소프트웨어적으로 구현시 
-> 다중 스레드가 동시에 락을 얻으려고 할 때 경쟁이 발생
-> 경쟁이 발생하면 오버헤드가 발생

하드웨어적으로 락을 구현시
락을 얻으려는 스레드가 바로 락을 얻을 수 없을때
-> 다른 스레드가 락을 가져갈 수 있다. 
-> 이 때 락을 획득하려는 스레드는 락이 풀릴 때까지 대기(스핀락(Spinlock))

 


장점 

1. 락 경쟁이 줄어들어 더 빠르게 처리가능
2. 컴파일러 최적화나 CPU 아키텍처와 같은 여러가지 요소로 인해 소프트웨어적으로 구현될 때 발생할 수 있는 다양한 버그와 같은 문제를 회피


  * 프트웨어적으로 구현될 때 발생할 수 있는 다양한 버그란?

     1. 락 대기 시간 최소화
        소프트웨어적으로 구현된 스핀락은 락을 얻을 때까지 반복적으로 비교-대기(spin-wait)를 하기 때문에 락 대기 시간이 길어짐
        하드웨어적으로 구현된 스핀락은 하드웨어적인 지원으로 인해 락을 얻을 때까지 바쁜 대기(busy waiting)를 하게 됨 -> 락 대기 시간을 감소시키는 효과를 가져옴 (아래 자세 설명)
 

       
     2. 인터럽트 처리에 따른 지연 시간을 최소화 
       소프트웨어적으로 구현된 스핀락은 인터럽트가 발생하면 락 대기를 중단하고 인터럽트 처리
       하드웨어적으로 구현된 스핀락은 인터럽트가 발생해도 락 대기를 계속할 수 있음

 

멀티코어에서는 락 없는 동기화 기법이 더 효율적인 이유

- 경쟁 조건(Race Condition)을 피할 수 있다. 

락 없는 동기화 기법도 사용 가능한 상황이 제한적이므로, 상황에 따라 적절한 동기화 기법을 선택해야 한다.


경쟁 조건이란? 

둘 이상의 스레드가 공유 데이터에 동시에 접근하려고 할 때 발생하는 문제

 -> 락을 사용하는 것이 보편적인 해결 방법 


* 문제발생상황

락은 여러 스레드가 동시에 락을 얻으려고 할 때 경쟁이 발생 -> 느린 성능과 데드락

 

* 해결 방법 

 쟁 조건을 피하기 위해 공유 데이터를 변경하지 않고, 대신 새로운 데이터를 만들어내는 방식

 -> 락 없는 동기화 기법(원자적 연산(Atomic Operation)


원자적 연산 

여러 스레드가 동시에 접근해도 안전하게 수행할 수 있으므로 경쟁 조건을 피할 수 있다. 
예를 들어, 멀티코어에서는 원자적 연산을 이용한 카운터 증가 등의 작업을 락 없이 처리할 수 있습니다.


원자적 연산을 이용한 카운터 증가란?

원자적 연산이 하나의 기계어 명령으로 수행되기 때문에 카운터 증가 등의 작업은 락 없이도 처리할 수 있다.(= 여러 개의 코어가 동시에 수행해도 서로 영향을 주지 않는다)
네, 자바에서는 java.util.concurrent.atomic 패키지를 통해 원자적 연산을 수행할 수 있습니다. 이 패키지는 다양한 데이터 타입에 대한 원자적 연산을 제공합니다.


예를 들어, AtomicInteger 클래스는 int 타입 변수의 값을 원자적으로 증가시키거나 감소시키는 기능을 제공합니다. 다음은 AtomicInteger 클래스를 사용한 예시 코드입니다.

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicExample {
    public static void main(String[] args) {
        AtomicInteger count = new AtomicInteger(0);

        // 여러 스레드에서 count 값을 원자적으로 증가시킴
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.out.println(count.incrementAndGet());
            }).start();
        }
    }
}
//위 코드는 AtomicInteger 클래스의 incrementAndGet() 메서드를 사용하여 count 변수를 원자적으로 증가시키고, 
//증가된 값을 출력합니다. 여러 개의 스레드에서 동시에 실행될 때에도 올바른 결과가 출력됩니다.

 

CAS 연산

동시성 제어에서 사용되는 원자적(atomic) 연산(실행 중에 다른 작업에 의해 방해받지 않고, 완전히 실행되거나 실행되지 않는 연산)

  • CAS 연산은 하드웨어 수준에서 지원
  • 멀티 스레드 환경에서 공유 자원에 대한 동시 접근을 안전하게 처리하는 데 사용
  • 대상 메모리 위치의 값이 예상 값과 같은지 비교한 다음, 조건이 충족되면 새로운 값으로 업데이트하는 작업 수행

-> 모든 과정이 원자적으로 수행되기 때문에, 여러 스레드가 동시에 CAS 연산을 수행하더라도 데이터 경쟁(race condition)이 발생하지 않음

 

스핀락(Spin Lock)이란?

- 임계구역(Critical Section) 진입이 불가할 때 가능할 때까지 whlie문을 돌면서 재시도하는 방식으로 구현된 락

Spin wait VS Busy waiting(동기화 기법)

  Busy Waiting 기법 Spin wait 기법 
공통점 둘 다 어떤 일이 끝날 때까지 계속해서 반복적으로 체크
차이점 기다리는 동안 다른 일을 할 수 있음 기다리는 동안 다른 일을 수행할 수 없음
ex. 사용 가능해질 때까지 일정한 간격으로 반복해서 체크 이벤트가 발생할 때까지 중단 없이 계속해서 체크
쓰이는 곳 멀티 스레드 환경,소프트웨어적으로 구현된 스핀락 싱글스레드 환경,하드웨어적으로 구현된 스핀락
//Spin wait
while (true) {
    if (conditionIsMet()) {
        break;
    }
}

//Busy waiting
while (!conditionIsMet()) {
    doSomethingElse();
}

 

 

하드웨어적으로 구현된 스핀락 : compare-and-swap (CAS) 연산

상황 여러 스레드가 공유하는 변수에 접근하는 경우, 스레드들이 변수 값을 동시에 변경하거나 읽어오는 경쟁 조건(race condition)이 발생
기법 종류 뮤텍스(mutex)나 세마포어(semaphore) CAS 연산
특징 시스템 자원을 많이 소모, 성능 저하 여러 스레드가 동시에 변수의 값을 변경하려고 할 때, 먼저 CAS 연산을 수행한 스레드가 변수의 값을 변경
-> 스레드 간의 경쟁 조건을 방지
-> 락(lock)이나 뮤텍스(mutex) 등의 동기화 기법을 사용하지 않아도 스레드 안전한 코드를 작성 가능

 

* 구현방식

1.variable의 현재 값을 읽어옵니다.
2.variable의 현재 값이 expected와 같은지 비교합니다.
3.값이 같다면, variable의 값을 new_value로 변경합니다.
4.값이 다르다면, 아무 작업도 수행하지 않고 false를 반환합니다.
5.CAS 연산은 여러 스레드가 공유하는 변수의 값에 대한 원자적인 변경을 보장하기 위해 사용됩니다. 



*특징

스레드 A와 B가 동시에 같은 변수의 값을 변경하려고 할 때, 
CAS 연산을 사용하면 두 스레드가 동시에 변수의 값을 변경하는 것을 방지할 수 있다. 
이를 통해, 스레드 간의 경쟁 조건(race condition)을 방지하고, 스레드 안전(thread-safe)한 코드를 작성할 수 있다.



*쓰는 이유

CAS 연산은 다중 스레드 프로그래밍에서 경쟁 조건(race condition)을 방지하고, 스레드 안전(thread-safe)한 코드를 작성하기 위해 사용

반응형

'OS' 카테고리의 다른 글

[OS] 메모리  (0) 2023.03.20
[OS] DeadLock(데드락)  (0) 2023.03.19
[OS] Process 동기화(세마포어,뮤텍스,모니터)  (0) 2023.03.13
[OS] Process  (0) 2023.03.06
[OS] CPU Scheduler  (1) 2023.03.06
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
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
글 보관함