[F-Lab 챌린지 12일차] TIL : 동기화

성수데브리·2023년 7월 11일
0

f-lab_java

목록 보기
10/73

멀티스레드 환경에서 가시성이란?

공유자원 A 을 사용하는 두 스레드가 있을 때,

A 의 값은 CPU 의 캐시영역과 RAM 영역에 모두 존재할 수 있다.

Thread1 의 A 에 대한 연산 결과가 CPU 캐시 메모리 존재할 시점에 Thread2 는 Thread1 의 쓰기 결과 값을 RAM 메모리에서 볼 수 없다.

이런 경우를 해결하는 것을 가시성이라한다.

동기화란?

협력적으로 실행되는 프로세스들이 마구잡이로 동시에 실행해서는 안 된다. 올바른 실행을 위해서는 동기화가 필요한데, 동기화란 특정 자원에 접근할 때 한 개의 프로세스만 접근하게 하거나 프로세스를 올바를 순서대로 실행하게 하는 것을 의미한다.

  • 실행 순서 제어 동기화 : 논리상 작업의 선, 후 관계가 분명한 경우 실행 순서를 제어하는 것. ex) Reader 프로세스는 Writer 프로세스가 완료되기 전까지 실행되면 안된다.
  • 상호 배제(Mutual Exclusion)를 위한 동기화 : 한 프로세스가 임계 구역에서 작업 중이면 다른 프로세스가 임계 구역에 들어갈 수 없도록 제어하는 것
  • 공유 자원 : 공통으로 사용하는 자원. 전역 변수, 파일, 입출력장치, 보조기억장치 등이 있다.
  • 임계 구역(Critical Section) : 공유 자원에 접근하는 코드 중 동시에 실행하면 문제가 발생하는 코드 영역.

동기화 도구

뮤텍스 락

  • 구현방법
    • 프로세스들이 공유하는 전역변수 lock 을 사용한다.
    • 한 프로세스가 임계 구역에 진입하면 lock 을 획득한다.
    • 다른 프로세스들은 lock 이 해제될때까지 반복적으로 체크한다. ( → busy wait 바쁜 대기 방식 )
      acquire(){
      	while(lock == true);
      	
      	lock = true;
      }
    • 임계구역에 진입했던 프로세스의 작업이 끝나면 lock 을 해제한다.
      release(){
      	lock = false;
      }
      acquire(); 
      // 임계 구역
      release();

세마포 & 모니터 : N 개의 프로세스 또는 스레드가 공유 자원에 접근할 때 상호 배제를 위한 동기화 장치

세마포

  • 종류 : 이진 세마포(binary semaphore), 카운팅 세마포(counting semaphore)
  • 세마포는 철도 신호기에서 유래한 단어. 프로세스는 임계 구역 앞에서 멈춤 신호를 받으면 잠시 기다리고, 가도 좋다는 신호를 받으면 임계 구역에 들어가게 된다.
  • 구현 방법 (카운팅 세마포)
    • 임계 구역에 진입할 수 있는 프로세스의 개수 혹은 사용 가능한 공유자원 개수를 나타내는 전역 변수 S

    • wait 신호를 보내는 함수 wait

      wait(){
      		while(S <= 0);
      		S--;
      }

      사용 가능한 자원 S 가 있는지 반복적으로 확인한다.

      가용 가능한 자원이 있으면 S 카운트를 감소하고 임계 구역에 진입한다.

    • 임계 구역에 들어가도 좋다는 신호를 보내는 함수 signal

      ```java
      signal(){
      	S++;
      }
      ```
      
      임계 구역에서 작업이 끝나면 S 를 1 증가시킨다. 
      wait();
      // 임계 구역
      signal();

뮤텍스 락 & 세마포어 차이

  • 동기화 대상의 개수가 세마포어는 N개 이다.
  • 뮤텍스는 상태가 0, 1 이므로 lock 을 소유하고 있는 프로세스만이 반납할 수 있다. 하지만 세마포어는 세마포어를 소유하지 않는 스레드도 반납할 수 있다.

모니터

세마포는 임계구역 앞뒤로 일일이 wait 과 signal 함수를 명시하는 것은 번거로운 일이며
함수 누락이다 순서가 잘못 될 경우 문제가 발생할 수 있다.

그래서 세마포에서 진보된 동기화 도구가 모니터이다.

  1. 공유 자원과 공유 자원에 접근하기 위한 인터페이스(통로)를 묶어 관리한다.
    프로세스는 반드시 인터페이스를 통해서만 공유 자원에 접근하도록 한다. 모니터를 통해 공유 자원에 접근하고자 하는 프로세스를 에 삽입하고 순서대로 하나씩 모니터에 들어갈 수 있다. 모니터 안에 항상 하나의 프로세스만 들어오도록 하여 상호 배제를 위한 동기화를 제공한다.

자바의 동기화 처리 장치

  1. synchronized
    • 공유 자원에 접근하는 스레드를 동기화하여 race condition 을 막는 장치 race condition : 임계구역임에도 잘못된 실행으로 여러 프로세스 또는 스레드가 동시 다발적으로 임계 구역의 코드를 실행하여 문제가 발생하는 경우
    • 코드 블록에 synchronized 키워드를 선언하면 해당 코드는 단 하나의 스레드만 실행할 수 있다.
  • 자바의 모든 객체는 모니터를 가지고 있으며, 모니터를 통해 스레드 동기화를 수행한다.
  1. volatile

    이 키워드를 적용한 변수는 L1, L2 등에 캐시를 참조하지 않고 직접 메모리를 참조하도록 한다.

    하지만 스레드 간의 동시 접근 동기화 문제는 synchronized 키워드로 해결해야 한다.

  2. jdk 1.5 부터 멀티스레드 프로그래밍을 더욱 편리하게 지원하는 java.util.concurrent 가 도입됨

    핵심 요소

    • 락, 세마포어

    • atomics

      • 원자성이란 더이상 쪼갤 수 없는 성질을 말한다.

        이 개념을 CS 에 적용하면 완전하게 실행되거나 그렇지 않다면 아예 실행될 수 없는 것을 말한다.

        원자성을 가지는 작업은 실행중에 종료되거나 중간에서 멈추지 않아야 한다.

        cnt += 1; 코드는 한 줄이지만 컴파일 해보면 여러 명령어로 분해된다.

        변수 cnt 에서 읽는 GETFIELD 와 쓰는 PUTFIELD 사이에 두 개의 명령어가 있다.

        ICONST_1 에 진입한 스레드에 interrupt 가 걸리며 작업이 중단이 되고,
        그 사이에 다른 스레드가 add() 메서드 작업을 수행해 cnt 값을 변경하면 두 스레드간 동기화가 깨지게 된다.

        cnt += 1; 코드는 원자성이 보장되지 않는 작업이다.

      • synchronized 키워드로 해결할 수 있지만 jdk1.5 부터 Atomic 클래스가 도입되었다.

        • Atomic 클래스는 기본 자료형이나 참조 자료형의 write 작업을 원자적으로 처리해준다.
        • CSA(compare-and-swap)을 사용한다. CAS 알고리즘이란 현재 스레드가 존재하는 CPU의 CacheMemory와 MainMemory에 저장된 값을 비교하여, 일치하는 경우 새로운 값으로 교체하고, 일치하지 않을 경우 기존 교체가 실패되고, 이에 대해 계속 재시도하는 방식
        • non-blocking 동기화 구현 장치 중 lock 함수를 보면, 스레드는 임계구역에 진입하기 전 while문으로 lock이 해제될 때까지 block된다.
          Atomics 클래스는 busy wait 을 하지 않는다.
    • 블로킹 큐

    • 래치

    • executor

0개의 댓글