락(Lock)에 대해서 알아보자.

2025. 5. 8. 13:36·공부/CS
목차
  1. 1. 락(Lock)이 왜 필요할까?
  2.  
  3. 2. 락에 대해서 알아보자.
  4. 임계 영역(Critical Section)
  5. 원자적 연산(Atomic Operation)
  6. 3. 락의 종류
  7. 3-1. 낙관적 락(Optimistic Lock)
  8. 3-2. 비관적 락(Pessimistic Lock)
  9. 3-3. 공유 락(Shared Lock)
  10. 3-4. 배타 락(Exclusive Lock)
  11. 4. 비관적 락 구현 시 발생할 수 있는 데드 락(Dead Lock)
  12. 4-1. 데드락을 해결하는 방법들
  13. 5. 게임에서 언제 락을 사용할까 ?
 

jungle-cs-study/2025-04/week05/bh_lock.md at main · Jungle-CS-Study/jungle-cs-study

Contribute to Jungle-CS-Study/jungle-cs-study development by creating an account on GitHub.

github.com


1. 락(Lock)이 왜 필요할까?

프로그램에서 프로세스는 단 하나지만, 스레드는 여러개가 존재할 수 있다. 2개의 스레드 A, B가 있다고 가정하고 둘 다 Coins 변수를 공유하고 있다고 생각해보자.

 

스레드 A와 B가 서로에게 영향을 주지 않고 독립적으로 수행된다면, 훌륭한 일이지만 안타깝게도 스레드 A가 Coins 변수를 사용하고 있을 때, 스레드 B도 사용하고 싶을 수 있다. 이렇게 될 경우 스레드 A와 스레드 B가 동시에 Coins 변수를 사용하고 있기에, 값이 어떻게 변화될 지 모르게 된다.

 

양자역학과 같이 유추할 수 없는 형태가 된다면, 변수를 사용하는 방법은 굉장히 어려워진다. 이 때, 락을 이용해서 문제를 해결할 수 있다.

 

락의 효능

  • 경쟁 상태 방지 : 여러 스레드가 동시에 공유 데이터를 수정할 때, 예측할 수 없는 결과를 방지함!
  • 데이터 일관성 : 공유 데이터가 모든 스레드에서 일관되게 보일 수 있도록 함!

 

2. 락에 대해서 알아보자.

락은 멀티 스레드 환경에서 공유 자원에 대한 접근을 관리하는 개념을 의미한다. 앞서서 말한 것과 같이 멀티스레드가 서로 공유하고 있는 자원을 사용할 때, 필연적으로 경쟁 상태(Race Condition)이 발생할 수 있다.

 

이러한 문제를 방지하고 데이터의 일관성을 유지하기 위해서 사용한다. 말 그대로 잠금(Lock)을 걸어서 공유 자원이 사용 중일 때, 다른 스레드가 접근하지 못하게 하는 방식이다.

 

락에서 사용되는 주요한 단어들을 알아보고, 락을 구현하는 여러 방식들에 대해서 살펴보자.

 

임계 영역(Critical Section)

임계 영역은 실질적으로 문제가 있을 것이라고 판단되는 코드의 영역을 의미한다. CS 이론들은 우리가 확인할 수 없는 H/W 영역에 존재하는 경우가 대다수인데, 임계 영역은 S/W에서 확인할 수 있다.

public void CalculateCoin(int count){
    coin = 1000;
    coin -= count; // 스레드가 동시 접근하면 문제가 발생할 수 있다!
}

우리가 작성하는 코드에서 공유 자원으로 사용되는 곳이 있으면 그게 임계 영역이 될 수 있다. 예를 들어, 여러 스레드가 동시에 같은 변수 coin을 수정하려고 할 때, 그 코드 부분이 임계 영역이 된다.

 

이러한 임계 영역들은 락으로 보호되어야 한다. 임계 영역을 적절히 보호하지 않으면 경쟁 상태(Race Condition) 가 발생하여 예상치 못한 결과가 나올 수 있다.

 

원자적 연산(Atomic Operation)

원자적 연산은 스레드가 실행하는 일의 단위처럼 사용된다.

 

원자적 연산은 다른 스레드에 의해서 중간에 중단되지 않으며, 완전히 실행되거나 전혀 실행되지 않는 연산을 의미한다. 연산이 분할할 수 없는(atomic) 단위로 취급된다.

int money = 0;  // 일반적인 연산
money++;        // (의외로) 복합 연산

대부분 프로그래밍 언어는 단일로 이루어진 연산을 사용하지만, 복합 연산을 사용하는 경우가 있다. money++와 같은 증감연산자가 대표적인데, money 값 읽기, 더하기, 쓰기로 구성되어 있다. 원자적 연산이 보장되지 않으면 이 과정에서 다른 스레드가 간섭할 때, 우리는 원하는 결과를 얻을 수 없다.

 

원자적 연산을 보장하여, 우리가 원하는 결과를 출력할 수 있도록 해야한다.

 

3. 락의 종류

3-1. 낙관적 락(Optimistic Lock)

낙관적 락은은 충돌이 드물게 발생한다고 가정하고 설계한다. 리소스에 접근할 때는 락을 걸지 않는데, 데이터에 대한 변경 사항을 적용하기 전에 데이터가 변경되었는지 확인하는 과정을 거친다.

 

만약에 데이터가 변경 되었다면 충돌 해결 방법을 적용하고 데이터를 저장한다. 동시 수정되는 경우가 없을 때, 자주 사용되는 방식이다.

 

3-2. 비관적 락(Pessimistic Lock)

낙관적 락과 반대로, 충돌이 자주 발생한다고 가정하고 설계한다. 리소스에 접근할 때 락을 흭득해야 하며, 락을 누가 사용중이라고 하면, 락이 없는 다른 스레드는 락을 흭득하기 전까지 대기하고 있어야 한다.

 

데이터의 일관성을 보장하는 좋은 방법. 비관적 락을 구현하는 방법에는 공유 락(Shared Lock)과 배타 락(Exclusive Lock)이 있다.

 

3-3. 공유 락(Shared Lock)

공유 락은 읽기 락(Read Lock)으로도 불린다. 공유 락이 걸린 데어티에 대해서는 읽기 연산만 가능하고 쓰기 연산이 불가능하다.

 

그렇기 때문에 데이터는 일관성을 유지하고 있으며, 공유 락이 걸린 데이터는 다른 스레드도 똑같이 공유 락을 흭득해서 읽기가 가능하다.

 

3-4. 배타 락(Exclusive Lock)

배타 락은 쓰기 락(Write Lock)으로도 불린다. 배타 락을 흭득한 스레드는 읽기 연산과 쓰기 연산을 모두 수행할 수 있는데, 스레드가 데이터에 대한 배타 락을 흭득하면, 다른 스레드는 배타 락이 걸린 데이터에 대해서 읽기/쓰기 작업을 수행할 수 없다.

 

이 경우엔 블로킹(Blocking) 상태가 되었다고 한다.

 

4. 비관적 락 구현 시 발생할 수 있는 데드 락(Dead Lock)

낙관적 락은 모든 스레드가 동시에 접근할 수 있기 때문에 데드 락 문제가 발생하지 않는다. 하지만, 비관적 락을 구현하면 데드 락 문제가 발생하게 된다.

 

데드 락은 스레드가 공유 자원의 락을 기다리느라, 무한정 대기하게 되는 상황을 의미한다.

 

2개의 스레드 A와 B가 있다.

 

A 스레드는 유저의 코인을 추가하는 일을 수행하고 있기 때문에 Coins 데이터가 필요하다. B 스레드는 코인을 유저에게 전송하는 일을 수행하고 있어 Coins와 User 데이터가 모두 필요하다.

 

그러면 이런 상황이 발생할 수 있다.

 

  1. A, B 스레드가 동시에 실행되었다.
  2. A 스레드가 Coins 데이터에 대한 락을 획득한다.
  3. B 스레드가 User 데이터에 대한 락을 획득한다.
  4. A 스레드가 작업을 계속하기 위해 User 데이터에 대한 락이 필요하지만, 이미 B 스레드가 점유하고 있어 대기한다.
  5. B 스레드도 작업을 진행하기 위해 Coins 데이터에 대한 락이 필요하지만, A 스레드가 점유하고 있어 대기한다.
  6. 유저는 게임이 느려진 것을 깨닫고 하염없이 프레임이 올라오기를 대기한다...🥲

 

이렇게 A, B 스레드는 서로가 보유한 자원을 기다리며 영원히 진행되지 못하는 데드락 상태에 빠지게 된다.

 

4-1. 데드락을 해결하는 방법들

  • 락 흭득 순서 통일
    • 모든 스레드가 데이터의 락을 흭득할 때, 항상 동일한 순서로 자원을 흭득하게 한다.
  • 타임아웃 도입
    • 락을 흭득하고 N초의 시간 뒤에 락 권한을 해제하게 한다.
  • 락 관리자 도입
    • 모든 락 권한을 관리하는 관리자를 도입한다. 데드 락이 발생할 가능성이 있는 락 요청을 방지한다.

 

5. 게임에서 언제 락을 사용할까 ?

금융 정보는 동서양을 막론하고 아주 중요하고 민감한 정보다. 락을 설명하는 예시 시나리오 중 계좌에 대한 예시가 많은데, 다음과 같이 흘러간다.

 

  1. 2,000원이 들어 있는 계좌 하나를 공유하는 독고남수 씨와 제임스 씨가 있다.
  2. 제임스 씨가 맥북 프로를 사고 싶어서 계좌에서 2,000원을 출금했다.
  3. 근데 동시에 독고남수 씨가 로또에 당첨되어서 당첨금 2,147,483,647원을 계좌에 입금되었다.
  4. 아뿔사! 은행 DB는 제임스 씨가 출금할 때, 계좌는 2,000원이라고 판단했다.
  5. 독고남수 씨의 당첨금 입금은 제임스 씨의 출금 과정을 처리하면서 발생했다.
  6. 결과적으로 계좌에는 0원이 남아있게 되었다.

 

상상도 할 수 없는 아주 끔찍한 일이다. 이와 같이 게임에서도 동서양을 막론하고 아주 중요하고 민감한 정보가 있다. 바로... 플레이어 데이터(Player Data) 다.

 

실의에 빠진, 독고남수 씨가 메이플스토리를 하면서 위안을 찾기로 했다. 오랜만에 게임에 접속한 그는 전 서버에서 아무도 깨지 못한 위업을 클리어 하기로 했다.

 

  1. 독고남수 씨는 2,147,483,647초 뒤, 엄청난 위업을 클리어 했다.
  2. A 서버에서 독고남수 씨에게 위업 클리어 보상을 제공했다.
  3. 근데 동시에 다른 B 서버에서 플레이어 데이터 동기화 작업이 발생했다.
  4. 아뿔사! B 서버는 A 서버가 클리어 보상을 받기 전 데이터를 저장했다.
  5. 독고남수 씨가 다시 게임에 접속했을 때, 엄청난 위업의 보상들은 사라져 있었다.

 

이런 일들이 발생할 수 있어서, 플레이어 데이터는 Lock을 사용해서 사전에 방지할 수 있어야 한다. 내가 사용하는 Unity 엔진에서는 C# 언어를 사용하고 있고 다음과 같이 플레이어 데이터에 Lock을 지정할 수 있다.

 

private static readonly object savedLock = new object();

lock(savedLock)
{
    Debug.Log("업적 데이터 락 흭득!");

    플레이어_데이터.Save();

    Debug.LogWarning("업적 데이터 락 해제!");
}

 

이외로도 보스 아이템 흭득, 캐시 샵에서 한정된 아이템 구매할 때, 길드 공동 계좌에서 돈을 입출금할 때 등 다양한 부분에서 Lock이 사용되고 있다.

'공부 > CS' 카테고리의 다른 글

[CS] 시스템 콜(System Call)  (0) 2024.10.18
SOLID 원칙은 무엇을 의미할까?  (0) 2023.06.21
[사운드 - LostArk 배경음악]  (0) 2019.08.21
  1. 1. 락(Lock)이 왜 필요할까?
  2.  
  3. 2. 락에 대해서 알아보자.
  4. 임계 영역(Critical Section)
  5. 원자적 연산(Atomic Operation)
  6. 3. 락의 종류
  7. 3-1. 낙관적 락(Optimistic Lock)
  8. 3-2. 비관적 락(Pessimistic Lock)
  9. 3-3. 공유 락(Shared Lock)
  10. 3-4. 배타 락(Exclusive Lock)
  11. 4. 비관적 락 구현 시 발생할 수 있는 데드 락(Dead Lock)
  12. 4-1. 데드락을 해결하는 방법들
  13. 5. 게임에서 언제 락을 사용할까 ?
'공부/CS' 카테고리의 다른 글
  • [CS] 시스템 콜(System Call)
  • SOLID 원칙은 무엇을 의미할까?
  • [사운드 - LostArk 배경음악]
태역
태역
  • 태역
    RYULAB
    태역
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 언어
        • C
        • C++
        • C#
      • 엔진, 프레임워크
        • Unity
        • Unreal
        • Electron
      • 공부
        • 디자인 패턴
        • 수학
        • CS
        • Git
        • 알고리즘
        • 자료구조
      • 코테
        • 프로그래머스
        • 백준
      • 독서
        • Effective C#
        • CLR via C#
        • 뇌를 자극하는 윈도우즈 시스템 프로그래밍
        • 오브젝트
        • CSAPP
        • OSTEP
      • 프로젝트
        • Unity
      • 개발 일지
        • 퓨처리티
        • 골든타임
      • 활동
        • 게임잼 후기
        • 게임제작동아리 브릿지
        • 크래프톤 정글
        • 기타
      • 기타
  • 블로그 메뉴

    • 링크

    • 공지사항

      • 2024 04 17
    • 인기 글

    • 태그

      티스토리챌린지
      오블완
      인프런 #인프런강의후기 #게임개발 #게임개발강의 #인강후기 #강의후기 #게임개발자 #인프런강의
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    태역
    락(Lock)에 대해서 알아보자.
    상단으로

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.