ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다중 스레드와 동기화: 성능과 안정성을 위한 최적의 방법
    swift 2023. 5. 21. 16:17

    Thread

     

    • Thread의 정의스레드는 동시성 프로그래밍을 구현하는데 사용 . 다중 스레드 프로그래밍을 통해 여러 작업을 동시에 실행하고 병렬처리를 통해 시간을 절약하거나 성능을 향상 시킬 수 있다.
    • 프로세스 내에서 실행되는 독립적인 실행 단위 . 각각의 스레드는 프로세스의 주소 공간을 공유하면서 동시에 실행될 수 있다. 다양한 작업을 병렬또는 동시에 처리하기 위해 사용됨.
    • Thread의 종류
      • Main Thread : 프로그램이 시작될 때 생성되는 기본 스레드. UI 처리하고 앱의 주요 동작 담당
      • Background Thread : 메인 스레드 이외의 스레드로 주로, 비동기 작업이나 병렬처리를 위해 사용 보통 오래걸리는 작업이나, 네트워크 요청 등을 처리할 때 유용
      • Dispatch Queue Thread : (작업 큐 스레드) GCD를 사용하여 비동기 작업을 관리하는 스레드.
      • GCD : 멀티스레딩을 위한 애플의 api 비동기적 작업을 처리하기 위해 사용. 복잡한 멀티 스레딩을 간편하게 구현할 수 있는 강력한 도구이며 ios 및 macOS 애플리케이션 개발에서 비동기 작업을 처리하는데 사용
      • Concurrent Thread (동시성 스레드) : 동시에 여러 작업을 처리할 수 있는 스레드. 여러 개의 동시성 스레드를 사용하여 병렬 처리를 구현할 수 있다.
      • Real-time thread : 실시간 시스템에서 사용되어 정확한 타이밍에 작업을 처리해야 하는 경우에 사용된다.

    Process

    • Process의 정의
    • 운영체제에서 실행중인 프로그램을 의미한다. 독립적으로 실행되며 자신만의 주소 공간, 자원, 스레드를 가지고 있다. 프로세스는 운영 체제에서 할당받은 자원을 사용하여 작업을 수행하고 서로 다른 프레세스 간에는 각각 독립적인 메모리 공간을 가지고 있다.
    • Thread와의 관계 ?
    • 하나의 프로세스는 최소 하나의 스레드를 가지고 있다. 여러 개의 스레드를 가지는 경우 동시에 실행될 수 있으며, 프로세스 내의 공유 자원에 접근하여 작업을 수행한다. 따라서 스레드는 프로세스의 실행 흐름을 구성하는 중요한 구성요소 이다.

     


    Multi-Thread

    • Multi-Thread를 왜 사용할까?
      • 동시성 , 응답성, 병렬 처리, 작업 분리, 자원 활용 , 병렬 알고리즘 및 병렬 프로그래밍을 통해서 동시성과 응답성을 개선하고 작업 처리 속도를 향상시키는 데에 사용된다. 또한 자원 활용, 작업 분리, 병렬 처리, 병렬 알고리즘 및 병렬 프로그래밍 등의 장점을 제공한다.
    • Swift에 Multi-Thread
      1. GCD(Grand Central Dispatch): GCD는 Swift에서 가장 일반적으로 사용되는 Multi-Thread 프로그래밍 방식아더,. GCD는 간단하면서도 강력한 API를 제공하여 스레드 생성 및 관리, 작업 큐 등을 처리할 수 있다.DispatchGroup: 여러 작업을 그룹화하고 완료 여부를 추적
      2. DispatchQueue: 작업을 비동기적으로 실행
        1. Operation과 OperationQueue:OperationQueue: Operation 을 관리하고 실행하는 역할
        2. Operation과 OperationQueue를 사용하면 작업 간의 의존성을 설정하거나 작업의 취소, 일시 중지, 재개 등을 조정할 수 있다.
        3. Operation: 실행할 작업을 나타냄.
      3. DispatchQueue와 DispatchQueue.concurrentPerform
        1. DispatchQueue : GCD의 Serial Queue 또는 Concurrent Queue를 생성하고 sync 또는 async 메서드를 사용하여 작업을 실행할 수 있다. 
        2. Serial Dispatch Queue: 한 번에 하나의 작업만 실행하는 queue. 작업이 순차적으로 실행되며, 한 작업이 완료된 후에야 다음 작업이 시작
        3. Concurrent Dispatch Queue: 여러 개의 작업을 동시에 실행할 수 있는 queue. 작업들이 병렬적으로 실행되며, 작업들이 상호 간섭 없이 동시에 실행
        4. concurrentPerform : 반복 작업을 병렬로 처리할 수 있다. 
      4. 콜백 함수: 비동기 작업이 완료되면 호출되는 콜백 함수를 사용하여 비동기 처리를 수행할 수 있다. 주로 완료 핸들러나 결과를 전달하는 콜백 함수를 작성하여 비동기 작업의 결과를 처리.
      5. NSOperation과 NSOperationQueue: NSOperation과 NSOperationQueue는 Operation과 OperationQueue의 Objective-C 버전으로, 기능적으로는 유사하다. 복잡한 작업 흐름과 의존성을 가진 작업을 처리할 때 유용함.
      6. DispatchQueue와 Combine: Swift의 Combine 프레임워크는 비동기 및 이벤트 기반 프로그래밍을 위한 라이브러리로, DispatchQueue와 결합하여 Multi-Thread를 구현할 수 있다.
    import Combine
    
    // 네트워크에서 데이터를 가져오는 작업 
    func fetchDataFromNetwork() -> AnyPublisher<Data, Error> {
        return URLSession.shared.dataTaskPublisher(for: URL(string: "https://api.example.com/data")!)
            .map(\.data)
            .eraseToAnyPublisher()
    }
    // 데이터를 처리하는 작업 
    func processResponse(data: Data) -> AnyPublisher<String, Error> {
        return Just(data)
            .decode(type: Response.self, decoder: JSONDecoder())
            .map { response in
                // 데이터 처리 로직 작성
                return response.processedData
            }
            .eraseToAnyPublisher()
    }
    
    let fetchDataQueue = DispatchQueue(label: "fetchDataQueue")
    let processQueue = DispatchQueue(label: "processQueue")
    
    fetchDataFromNetwork()
        .subscribe(on: fetchDataQueue) // fetchDataFromNetwork를 fetchDataQueue에서 실행
       // flatMap :데이터를 가져온 후에 데이터를 처리하는 작업 
    		 .flatMap { data in
            return processResponse(data: data)
                .subscribe(on: processQueue) // processResponse를 processQueue에서 실행
        }
        .sink(receiveCompletion: { completion in
            // 작업 완료 처리
        }, receiveValue: { result in
            // 최종 결과 처리
        })

    Thread-Lock

    • Thread를 남용할 경우 어떤 결과가 나타날까?
      1. 복잡성과 버그: Thread를 많이 사용하면 코드의 복잡성이 증가하고 버그가 발생할 가능성이 높아진다. 다중 스레드 간의 동기화 문제, 경쟁 상태 (race condition), 교착 상태 (deadlock) 등의 문제가 발생할 수 있다.
      2. 성능 저하: 스레드를 많이 생성하고 관리하면 컨텍스트 전환이 발생하고 자원을 소비하므로 성능이 저하될 수 있다. 불필요한 스레드를 생성하거나 작은 작업에 스레드를 할당하는 경우 오버헤드가 발생할 수 있음.
      3. 리소스 사용과 확장성: 스레드는 시스템 자원을 사용하므로 스레드를 많이 생성하면 시스템 리소스를 소모하게 된다. 또한, 많은 스레드를 관리하는 것은 복잡하며 확장성에 제약이 있을 수 있음
      4. 안정성과 신뢰성: 스레드를 잘못 사용하면 안정성과 신뢰성에 문제가 발생할 수 있다. 스레드 간의 동기화를 올바르게 처리하지 않으면 데이터의 일관성이 깨질 수 있거나 예기치 않은 동작이 발생할 수 있다.
    • NSLock 이란 ?NSLock을 사용하여 임계 영역을 보호하는 패턴
      1. NSLock 인스턴스를 생성
      2. 임계 영역에 진입하기 전에 NSLock 잠금
      3. 임계 영역에서 작업을 수행
      4. 임계 영역을 빠져나온 후에 NSLock을 잠금 해제
      5. NSLock은 일반적으로 상호 배제가 필요한 코드 블록 또는 메서드 내에서 사용됨, 여러 스레드가 동시에 해당 코드 블록 또는 메서드를 실행하지 못하도록 보장하여 경쟁 상태나 데이터 일관성 문제를 방지할 수 있다.
    • NSLock은 Objective-C에서 제공되는 동기화 도구로, 여러 스레드 간에 상호 배제를 보장하기 위해 사용된다. NSLock은 단일 스레드가 임계 영역 (critical section)에 진입하고 실행하는 동안 다른 스레드가 해당 영역에 접근하지 못하도록 막는것을 말한다.
Designed by Tistory.