비동기 프로그래밍

2023. 12. 25. 22:01·프로그래밍 언어/C#

🗓️ 주제

  • .Net에서 비동기 처리에 대해 (Task) 학습(2023/11/16, 2023/11/22)
  • 비동기 프로그래밍의 이점과 UniTask의 필요성(2023/11/20)

🎦 비동기 프로그램

동기와 비동기

  • 동기 : 수행 주체(스레드)가 하나인 실행
    • 스레드가 하나이면 모든 코드를 혼자 실행하며 다음 단계의 실행은 현재 코드의 수행이 끝나야만 실행 가능
    • 작업이 완료되기를 기다리는 방식
    • 현재 줄의 코드가 완료되어야만 다음 코드를 실행
  • 비동기 : 수행 주체(스레드)가 다수인 실행
    • 스레드가 서로의 코드를 기다리지 않고 개별적으로 작업 수행
    • 메인 스레드에서 별도의 스레드를 생성하여 해당 스레드가 개별 작업을 맡고 작업이 완료되면 결과를 메인 스레드로 전달하는 형식

비동기 프로그래밍의 장점

  • 성능 병목 현상을 방지하고, 애플리케이션의 전체적인 응답성을 향상시킬수 있다.
  • 반응성 향상
    • 액세스 속도가 느리고 지연되는 작업을 할 때(ex. 웹 리소스 다운) 동기 프로그래밍에서는 해당 작업 동안 전체 애플리케이션이 중지되지만, 비동기 프로그래밍에서는 중지되지 않고, 다른 작업을 계속 수행할 수 있다.
      • 지원 메서드
      애플리케이션 영역 비동기 메서드가 있는 .NET 형식
      웹 액세스 https://learn.microsoft.com/ko-kr/dotnet/api/system.net.http.httpclient
      파일 작업 JsonSerializer
      StreamReader  
      StreamWriter  
      XmlReader  
      XmlWriter  
      WCF 프로그래밍 https://learn.microsoft.com/ko-kr/dotnet/framework/wcf/synchronous-and-asynchronous-operations
    • 동기 프로그램은 한 개의 스레드를 사용하기 때문에 하나의 프로세스가 차단되면 모든 프로세스가 차단됨. 그렇기 때문에 응답이 중지되면 더 기다리지 않고 애플리케이션이 실패했다고 결론 내림. 반대로 비동기 프로그램은 다수의 스레드가 존재하기 때문에 UI에 계속 응답할 수 있음. 그렇기 때문에 다른 작업을 하고 있음에도 창의 크기를 바꾸거나 종료를 할 수 있음
  • 작성이 간편
    • C#의 async/await 키워드를 사용하면 쉽게 비동기 메서드를 만들 수 있음
      • 비동기 메서드 : async 키워드를 사용해서 정의한 비동기 메서드
    public **async** Task GetUrlContentLengthAsync()
    {
        var client = new HttpClient();
    
        Task getStringTask =
            client.GetStringAsync("<https://learn.microsoft.com/dotnet>");
    
        DoIndependentWork();
    
        string contents = **await** getStringTask;
    
        return contents.Length;
    }
    
    void DoIndependentWork()
    {
        Console.WriteLine("Working...");
    }
    

비동기 프로그래밍의 단점

  • 비동기 애플리케이션을 쓰는 방법이 복잡해서 사용과 디버깅, 유지 관리가 어려울 수 있다.
  • 다수의 스레드들이 특정 자원을 공유할 때 자원의 상태 변화나 접근 순서에 따라 문제가 발생하게 됨 → 스레드 동기화 기법을 통해 해결할 수 있다.

🖥️ 프로세스(Process)

  • 프로그램을 실행하는 과정

📀 스레드(thread)

  • 프로세스를 구성하는 작업 단위
  • 싱글 스레드 환경 : 프로세스를 구성하는 스레드가 하나
  • 멀티 스레드 환경 : 프로세스를 구성하는 스레드가 여러개

멀티스레딩

장점

  • 성능 향상
    • 2개 이상의 물리코어를 가진 컴퓨터가 하나의 프로세스를 여러 스레드에게 작업을 나누어 할당한다면 작업이 빨라짐
    • 물리코어 : 컴퓨터에서 프로그래밍을 실행하는 일을 하는 일꾼
      • 유니티의 멀티스레딩은 물리코어 1당 하나의 스레드를 만든다.

단점

  • 경쟁 조건(Race Condition)
    • 독립된 두 작업이 동시에 같은 값을 사용하려고 할 때 그들 사이의 경쟁에 의해서 실행 결과를 예측할 수 없게 되는 것.
    • ex) A스레드와 B스레드가 동시에 작동하고 있고, a라는 숫자에 각각 곱하기, 나누기를 하고 있다면 결과를 예측할 수 없다.
👉멀티 스레딩 환경에서는 각 스레드들이 병렬(여러 명의 일꾼이 동시에 각자의 일을 처리함)로 일들이 수행되기 때문에 경쟁 조건이 발생할 가능성이 있다.

 

  •  데드락
    • 서로 아무것도 못하고 대기하는 상황이 지속될 때
👉멀티 스레딩 환경에서 스레드들의 할 일을 잘못 정하면 각 스레드들의 일이 꼬여서 아무일도 하지 못하는 데드락 상태가 발생할 수 있다.
  • 종속성 문제
    • 스레드들의 작업이 종속성을 가지지 않아서 병렬로 처리하기 때문에 어떤 단계가 먼저 끝날지 예측할 수 없을때 생기는 문제
👉 멀티 스레딩 환경에서는 각 일들이 동시에 실행되고, 서로의 일이 연관이 있는지 스레드들은 모르기 때문에 종속성 문제가 발생할 수 있다.

동작 방법

  1. 스레드가 동작할 스택 할당
    1. 유저 모드 : 1MB, 커널 모드 : 12KB
  2. 스레드 생성
  3. 현재 프로세스에서 로딩된 모든 DLL에 스레드 생성을 통보
  4. 스레드 삭제
  5. 사용한 메모리와 자원 반환
  6. 현재 프로세스의 모든 DLL에 스레드 삭제를 통보
🚫 멀티 스레드의 문제점
작업 부하가 크다(스레드 사용에 따른 오버헤드)
🚫 스레드 생성시 주의 사항
오버헤드가 발생할 수 있다. 스레드의 생성/삭제 마다 메모리 할당과 전체 DLL에 스레드 생성/삭제를 통보하기 때문.

작업 스케쥴링

  • 어떤 스레드가 CPU 자원을 얼마나 사용할지 CPU가 결정한다.
    • 스케쥴링은 20ms 단위로 반복해서 수행된다.
    • 1 CPU가 여러개의 스레드에 대한 스케쥴링을 하게되면 큰 부담이 된다.
    • 하지만 여러개의 CPU를 탑재한 컴퓨터에서는 CPU의 활용을 높히는 좋은 수단이다.
      • 스레드 사용은 CPU의 분산처리를 가능하게 해서 CPU 성능을 끌어올린다.
  • 스레드가 스케쥴링 되어서 다음 스레드로 변경되면 컨텍스트 스위칭이 발생한다.

컨텍스트 스위칭(Context Switching)

  • 데이터 전환
  1. CPU는 작업을 위해 필요한 데이터를 레지스터와 가상 공간에 저장한다.
  2. 작업이 전환되면 레지스터의 내용과 참조하던 가상 공간을 전환한다.

🌀 스레드 풀(Thread Pool)

  • .NET에서 스레드 사용의 부담과 불편을 줄이기 위해 제공
    • System.Threading.ThreadPool
  • 스레드들이 담겨있는 수영장이라고 생각하면 됨
  • 작업이 끝났을때 스레드가 파괴되지 않고 스레드 풀로 복귀해 다음 작업을 대기한다

동작 방법

  1. 스레드 풀의 Queue에 작업이 Enqueue
    1. 델리게이트 형태로 Enqueue 됨
  2. Queue에 작업이 쌓이면 스레드 풀에서 대기중인 스레드가 Deque하고 작업 수행
    1. 대기중인 스레드가 없다면 스레드 생성
    2. 기본적으로 스레드 풀은 하나의 스레드를 가지고 있으며 기다리는 작업이 Queue에 쌓일 경우 추가 스레드를 생성해 Queue 내부의 작업을 해치운다.
  3. 작업이 완료된 스레드는 스레드 풀로 복귀
  4. 모든 작업이 완료된다면 일정 시간(기본 2분)동안 대기한 후 스레드 풀의 스레드들이 스스로 파괴된다.
    1. 불필요한 자원 점유 해제

장점

  • 스레드를 재사용해서 스레스의 생성/파괴에서 오는 오버헤드 줄임
  • 스레드 생성시 CPU별로 스레드가 할당되어 멀티CPU에 대한 스레드 할당이 자체적으로 최적화된 로직으로 수행된다.

QueueUserWorkItem()

  • 스레드 풀에 작업 Enqueue
    • QueueUserWorkItem(WaitCallback callBack);
    • QueueUserWorkItem(WaitCallback callBack, object state);
    • WaitCallback 델리게이트로 작업 전달
    • object state로 델리게이트에서 사용될 파라미터 전달

📜참고자료

비동기 프로그래밍 - 개요

유니티의 멀티스레딩

Unitask cancellation. What is the difference between Task and Coroutine?

유니티 - 잡 시스템(Job System)

'프로그래밍 언어 > C#' 카테고리의 다른 글

C#에서 var를 사용하는 이유와 주의사항  (0) 2024.02.26
Singleton VS DI  (1) 2024.02.12
람다식 () =>  (0) 2023.11.01
C#과 .NET Framework  (0) 2023.10.08
스택 프레임(Stact Frame)과 스택 오버 플로우(Stack Overflow)  (0) 2023.10.03
'프로그래밍 언어/C#' 카테고리의 다른 글
  • C#에서 var를 사용하는 이유와 주의사항
  • Singleton VS DI
  • 람다식 () =>
  • C#과 .NET Framework
가든_
가든_
  • 가든_
    Code Garden
    가든_
  • 전체
    오늘
    어제
    • 글 목록 (60)
      • 프로그래밍 언어 (11)
        • JAVA (0)
        • C++ (2)
        • C# (9)
      • 개발툴 (24)
        • Visual Studio (0)
        • Visual Studio Code (1)
        • Eclipse (1)
        • Unity (19)
        • Unreal (0)
        • Spring (1)
        • SpringBoot (0)
        • Vue (2)
      • 디자인 패턴 (6)
      • 백엔드 (4)
        • MySQL (1)
        • Servlet (3)
      • 프론트엔드 (4)
        • HTML (3)
        • CSS (0)
        • Javascript (1)
      • 알고리즘 (10)
        • 공식 (3)
        • 백준 (6)
        • SW Expert Academy (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    행동 UML 다이어그램
    Reflex
    클래스 어댑터
    swea2112
    Adaptee
    HTML
    오브젝터 어댑터
    Abstract Factory 패턴
    MVC
    ()=>
    SetTile
    스택
    12738
    Adapter 패턴
    구조적 UML 다이어그램
    UniRX
    FixedUpdate
    런타임 상수
    DI
    RDBM
    컴파일 상수
    다이어그램 그리기
    Factory 패턴
    c#
    Unity
    Java
    상태공간트리
    구조패턴
    Proxy 패턴
    chatGPT
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
가든_
비동기 프로그래밍
상단으로

티스토리툴바