Python의 멀티스레딩 [코딩 예제 포함]

게시 됨: 2020-11-30

코드를 개선하고 더 빠르게 만드는 것은 Python에 대한 기본 지식을 습득한 후의 다음 단계입니다. 멀티스레딩은 "스레드"를 사용하여 최적화를 달성하는 방법 중 하나입니다. 이 스레드는 무엇입니까? 그리고 이것들은 프로세스와 어떻게 다릅니까? 알아 보자.

이 튜토리얼을 마치면 다음에 대한 지식을 갖게 될 것입니다.

  • 쓰레드와 프로세스란?
  • 멀티스레딩은 어떻게 달성됩니까?
  • 그 한계는 무엇입니까?
  • 언제 멀티스레딩을 사용합니까?

세계 최고의 대학에서 온라인 데이터 과학 과정배우십시오 . 이그 제 큐 티브 PG 프로그램, 고급 인증 프로그램 또는 석사 프로그램을 획득하여 경력을 빠르게 추적하십시오.

목차

파이썬의 스레드

우리는 멀티태스킹을 생각할 때 병렬 실행을 생각합니다. 다중 스레딩엄격하게 병렬 실행이 아닙니다. 스레드는 독립적으로 실행되는 프로그램의 다른 부분에 대한 실행 흐름의 별도 엔터티로 생각할 수 있습니다. 따라서 본질적으로 스레드는 병렬로 실행되지 않지만 Python은 한 스레드에서 다른 스레드로 너무 빨리 전환하여 병렬인 것처럼 보입니다.

반면에 프로세스는 엄격하게 병렬이며 더 빠른 실행을 위해 다른 코어에서 실행됩니다. 스레드는 다른 프로세서에서 실행할 수도 있지만 기술적으로 병렬로 실행되지는 않습니다.

스레드가 병렬로 실행되지 않으면 어떻게 하면 작업을 더 빠르게 만들 수 있을까요? 대답은 항상 처리 속도를 높이는 것은 아니라는 것입니다. 멀티스레딩은 특히 스레드가 처리 속도를 높이는 작업에 사용됩니다.

스레드의 모든 정보는 스레드 제어 블록(TCB) 에 포함 됩니다. TCB는 다음과 같은 주요 부분으로 구성됩니다.

  1. 고유한 TID – 스레드 식별자
  2. 프로세스에서 스레드의 스택을 가리키는 스택 포인터
  3. 스레드에서 현재 실행 중인 명령어의 주소를 저장하는 프로그램 카운터
  4. 스레드 상태(실행 중, 준비됨, 대기 중, 시작 또는 완료)

즉, 프로세스에는 코드, 데이터 및 모든 파일을 공유하는 여러 스레드가 포함될 수 있습니다. 그리고 모든 쓰레드는 접근할 수 있는 별도의 레지스터와 스택을 가지고 있습니다.

이제 스레드가 공통 데이터와 코드를 사용하는 경우 다른 스레드를 방해하지 않고 어떻게 모두 사용할 수 있는지 궁금할 것입니다. 이것은 이 튜토리얼의 뒷부분에서 이야기할 멀티스레딩의 가장 큰 한계입니다.

컨텍스트 스위칭

이제 위에서 설명한 대로 스레드는 병렬로 실행되지 않고 결과적으로 실행됩니다. 따라서 한 스레드 T1이 실행을 시작하면 다른 모든 스레드는 대기 모드로 유지됩니다. T1의 실행이 완료된 후에만 대기 중인 다른 스레드가 실행을 시작할 수 있습니다. Python은 한 스레드에서 다른 스레드로 너무 빨리 전환하여 병렬 실행처럼 보입니다. 이 전환을 '컨텍스트 전환'이라고 합니다.

다중 스레드 프로그래밍

스레드를 사용하여 큐브 및 제곱 연산을 수행하는 아래 코드를 고려하십시오.

스레딩 가져오기

데프 큐브 (n) :
print( "큐브: {}" .format(n * n * n))

데프 제곱 (n) :
print( "정사각형: {}" .format(n * n))

__name__ == "__main__"경우 :
# 스레드 생성
t1 = threading.Thread(대상=제곱자, 인수=( 5 ,))
t2 = threading.Thread(대상=큐버, 인수=( 5 ,))

# 스레드 t1 시작
t1.start()
# 스레드 t2 시작
t2.start()

# t1이 완료될 때까지 대기
t1.join()
# t2가 완료될 때까지 기다립니다.
t2.join()

# 두 스레드가 모두 완료됨
print( "완료!" )

#산출:
정사각형: 25
큐브: 125
완료!

이제 코드를 이해하려고 합니다.

먼저 모든 작업을 담당하는 Threading 모듈을 가져옵니다. 메인 내부에서 Thread 클래스의 하위 클래스를 생성하여 2개의 스레드를 생성합니다. 해당 스레드에서 실행해야 하는 함수인 대상과 해당 함수에 전달해야 하는 인수를 전달해야 합니다.

이제 스레드가 선언되면 스레드를 시작해야 합니다. 이는 스레드 에서 시작 메서드를 호출하여 수행됩니다. 일단 시작되면 주 프로그램은 스레드가 처리를 마칠 때까지 기다려야 합니다. 대기 방법을 사용 하여 메인 프로그램이 일시 중지하고 스레드 T1과 T2가 실행을 마칠 때까지 기다립니다.

필독: 초보자를 위한 Python 챌린지

스레드 동기화

위에서 논의한 것처럼 스레드는 병렬로 실행되지 않고 대신 Python이 서로 전환합니다. 따라서 이상한 동작을 피하기 위해 스레드 간에 정확한 동기화가 매우 중요합니다.

경쟁 조건

동일한 프로세스에 있는 스레드는 공통 데이터와 파일을 사용하므로 여러 스레드 간의 데이터에 대한 "경합"이 발생할 수 있습니다. 따라서 여러 스레드에서 데이터 조각에 액세스하는 경우 두 스레드 모두에서 데이터를 수정하고 예상한 대로 결과를 얻지 못할 것입니다. 이를 경쟁 조건이라고 합니다.

따라서 동일한 데이터에 액세스할 수 있는 두 개의 스레드가 있는 경우 특정 스레드가 실행 중일 때 둘 다 액세스하고 수정할 수 있습니다. 따라서 T1이 실행을 시작하고 일부 데이터를 수정하면 T2는 절전/대기 모드에 있습니다. 그런 다음 T1은 실행을 중지하고 동일한 데이터에 대한 액세스 권한이 있는 T2에 제어를 넘겨주는 절전 모드로 전환합니다. 따라서 T2는 이제 동일한 데이터를 수정하고 덮어쓰므로 T1이 다시 시작될 때 문제가 발생합니다.

스레드 동기화 의 목표는 이러한 경쟁 조건이 발생하지 않고 코드의 중요한 섹션이 동기화된 방식으로 스레드에서 한 번에 하나씩 액세스하도록 하는 것입니다.

자물쇠

경쟁 조건과 그 결과를 해결하고 방지하기 위해 스레드 모듈은 스레드 동기화를 돕기 위해 세마포어를 사용 하는 잠금 클래스를 제공합니다. 세마포어는 바이너리 플래그일 뿐입니다. "약속"(1에 해당) 또는 "비 약혼"(0에 해당) 값을 갖는 전화 부스의 "약속" 기호로 간주합니다. 따라서 스레드가 잠금이 있는 코드 세그먼트를 만날 때마다 잠금이 이미 1 상태인지 확인해야 합니다. 그렇다면 사용할 수 있도록 0이 될 때까지 기다려야 합니다.

Lock 클래스에는 두 가지 기본 메서드가 있습니다 .

  1. 취득([차단]) : 취득 메소드는 차단 매개변수 True 또는 False받습니다. 스레드 T1에 대한 잠금이 True로 차단하여 시작된 경우 코드의 중요한 섹션이 다른 스레드 T2에 의해 잠길 때까지 기다리거나 차단된 상태로 유지됩니다. 다른 스레드 T2가 잠금을 해제하면 스레드 T1이 잠금을 획득하고 True 를 반환합니다 .

반면에 스레드 T1에 대한 잠금이 매개변수 차단을 False 로 사용하여 시작된 경우 임계 구역이 스레드 T2에 의해 이미 잠겨 있는 경우 스레드 T1은 기다리지 않거나 차단된 상태로 유지됩니다. 잠긴 것으로 확인되면 즉시 False를 반환하고 종료합니다. 그러나 코드가 다른 스레드에 의해 잠겨 있지 않은 경우 잠금을 획득하고 True 를 반환 합니다.

release() : 잠금 해제 메서드가 호출되면 잠금을 해제하고 True를 반환합니다. 또한 잠금이 해제되기를 기다리는 스레드가 있는지 확인합니다. 있는 경우 정확히 그 중 하나가 잠금 장치에 액세스할 수 있습니다.

그러나 잠금이 이미 잠금 해제되어 있으면 ThreadError가 발생합니다.

교착 상태

다중 잠금을 처리할 때 발생하는 또 다른 문제는 교착 상태입니다. 교착 상태는 여러 가지 이유로 스레드가 잠금을 해제하지 않을 때 발생합니다. 다음을 수행하는 간단한 예를 살펴보겠습니다.

스레딩 가져오기

l = 스레딩.Lock()
# 1차 획득 전
l.획득()
# 2차 획득 전
l.획득()
# 이제 잠금을 두 번 획득했습니다.

위의 코드에서 우리는 취득 메소드를 두 번 호출하지만 처음 취득한 후에는 해제하지 않습니다. 따라서 파이썬은 두 번째 획득 문을 볼 때 이전 잠금을 해제하지 않았기 때문에 무기한 대기 모드로 들어갈 것입니다.

이러한 교착 상태 조건은 사용자가 깨닫지 못하는 사이에 코드에 침투할 수 있습니다. 릴리스 호출을 포함하더라도 코드가 도중에 실패할 수 있으며 릴리스가 호출되지 않고 잠금이 잠긴 상태로 유지됩니다. 이를 극복하는 한 가지 방법 은 컨텍스트 관리자라고도 하는 with as 문을 사용하는 것입니다. with as 문을 사용하면 어떤 이유로든 처리가 완료되거나 실패하면 잠금이 자동으로 해제됩니다.

읽기: Python 프로젝트 아이디어 및 주제

가기 전에

앞에서 논의한 것처럼 멀티스레딩은 실제로 병렬로 실행되지 않기 때문에 모든 애플리케이션에서 유용하지 않습니다. 그러나 멀티스레딩의 주요 응용 프로그램은 데이터가 로드되기를 기다리는 동안 CPU가 유휴 상태로 있는 I/O 작업 동안입니다. 멀티스레딩은 CPU의 이 유휴 시간이 다른 작업에 활용되어 최적화에 이상적이기 때문에 여기서 중요한 역할을 합니다.

데이터 과학에 대해 자세히 알아보려면 작업 전문가를 위해 만들어졌으며 10개 이상의 사례 연구 및 프로젝트, 실용적인 실습 워크숍 , 업계 전문가와의 멘토링, 1 - 업계 멘토와 일대일, 400시간 이상의 학습 및 최고의 기업과의 취업 지원.

파이썬에서 쓰레드란?

스레드는 Python에서 실행되도록 예약될 수 있는 프로세스 내의 엔터티입니다. 일반 용어로 스레드는 컴퓨터에서 수행되는 계산 프로세스입니다. 개발자가 다른 스크립트와 독립적으로 실행할 수 있는 프로그램 내의 이러한 명령 집합입니다. 스레드를 사용하면 병렬 처리를 사용하여 응용 프로그램 속도를 높일 수 있습니다. 작업이 병렬로 작동할 수 있도록 하는 가벼운 프로세스입니다. 스레드는 독립적으로 작동하고 CPU 사용을 최대화하므로 CPU 성능이 향상됩니다.

파이썬에서 다중 스레드의 용도는 무엇입니까?

다중 스레딩은 CPU의 도움으로 스레드 사이를 빠르게 전환하여 많은 스레드가 동시에 작동할 수 있도록 하는 Python 프로그래밍의 스레딩 기술입니다(컨텍스트 전환이라고 함). 작업을 여러 개의 개별 섹션으로 나눌 수 있을 때 멀티스레딩을 사용합니다. 예를 들어, 복잡한 데이터베이스 쿼리를 수행하여 데이터를 얻고 해당 쿼리를 수많은 개별 쿼리로 분할해야 한다고 가정합니다. 이 경우 각 쿼리에 스레드를 할당하고 모두 병렬로 실행하는 것이 좋습니다.

스레드 동기화란 무엇입니까?

스레드 동기화는 둘 이상의 동시 프로세스 또는 스레드가 프로그램의 중요한 부분을 동시에 실행하지 않도록 보장하는 방법으로 설명됩니다. 동기화 방법은 중요한 섹션에 대한 프로세스의 액세스를 제어하는 ​​데 사용됩니다. 프로그램 내에서 둘 이상의 스레드를 시작하면 여러 스레드가 동일한 리소스에 액세스하려고 시도하여 동시성 문제로 인해 예기치 않은 결과가 발생할 수 있습니다. 예를 들어, 많은 스레드가 동일한 파일 내에서 쓰기를 시도하는 경우 스레드 중 하나가 데이터를 재정의할 수 있거나 한 스레드가 열리고 다른 스레드가 동일한 파일을 닫을 때 데이터가 손상될 수 있습니다.