주제:

Thread의 safety와 unsafety에 대해서 공부하고 스터디하여 메모하기

1. Thread-safety와 unsafety란 무엇인가?

Thread-safety는
멀티 스레드 프로그래밍에서 
어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 
프로그램의 실행에 문제가 없음을 뜻함.

보다 엄밀하게는 하나의 함수가 한 스레드로부터 호출되어 실행 중일 때, 
다른 스레드가 그 함수를 호출하여 동시에 함께 실행되더라도 
각 스레드에서의 함수의 수행 결과가 올바로 나오는 것으로 정의함.

반면 Thread-unsafety는 그렇지 못한 것을 의미.

2. 이러한 특성이 생기는 이유는 무엇인가?

멀티스레딩 환경에서 
여러 스레드가 동시에 공유 데이터나 자원을 접근하고 수정할 때 
발생하는 문제를 해결하기 위함.

두 개 이상의 스레드나 프로세스가 서로가 가진 리소스를 기다리며 무한히 대기한다거나, 
하나의 스레드가 작업을 완료하기 전에 다른 스레드가 중간에 접근하여 
데이터를 변경하는 문제점이 발생할수도 있음.

Thread-safety는 프로그램의 안전한 동작을 보장하기 위해 
스레드 간의 동기화와 데이터 공유를 적절히 관리하는 역할을 함.

* 참고

https://velog.io/@gwak2837/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%94%A9

Thread-safety 관련 파이썬 코드 :

works 리스트에 존재하는 0부터 999까지의 원소에 1000을 곱한 결과를
results 리스트에 순서대로 저장하는 코드.

##### 멀티스레딩 전 #####
works = [x for x in range(1000)]
results = []

for work in works:
    result = work * 1000
    results.append(result)
    
print("Finished")
##### 멀티스레딩 후 #####

import threading

def calculate(partial_works):
    for work in partial_works:
        result = work * 1000
        results.append(work)

works = [x for x in range(1000)]
results = []

### 스레드 개수와 스레드 리스트 ###
thread_count = 10
threads = []

### 새로운 스레드 생성/실행 후 스레드 리스트에 추가 ###
# (파이썬에서 각 스레드는 target으로 주어진 함수를 실행한다.
# 그리고 해당 함수의 매개변수는 args를 통해 튜플 형태로 넘겨줄 수 있다.) 
for i in range(thread_count):
    thread = threading.Thread(target=calculate, args=(works[i * 100 : (i + 1) * 100],),) 
    # -> .Thread(): 스레드(객체)를 새로 생성한다.
    # (튜플 특성 상 함수 매개변수가 하나일 땐 마지막에 ,를 넣어줘야 한다.)
    thread.start() 
    # -> .start(): 해당 스레드가 target으로 넘겨받은 함수를 병렬로 실행한다.
    threads.append(thread)

### 메인 스레드는 각 스레드의 작업이 모두 끝날 때까지 대기 ###
for thread in threads:
    thread.join() 
    # -> .join(): 
    # 해당 스레드(새로 생성된 스레드)의 실행이 끝날 때까지 
    # join() 함수를 호출한 스레드(메인 스레드)는 대기한다.
    
print("Finished")
# -> 메인 스레드는 각 스레드의 작업이 모두 끝난 후 Finished를 출력한다.

주의할 점:
스레드의 실행 순서에 따라 results 리스트의 원소 순서가 달라질 수 있다.

정리

  1. 병렬 처리할 부분을 함수로 만든다.
  2. 슬라이싱 등을 통해 작업을 분할한다.
  3. 각 스레드에게 함수와 분할된 작업을 건내준다.
  4. 각 스레드가 처리한 결과를 모은다.

튜플 매개변수 개념 관련 참고

##### 튜플 매개변수 개념 관련 참고 코드 #####

def greet(name, age="default_age", location="default_location"):
    print(f"Hello, my name is {name}. I am {age} years old and I am from {location}.")

### 매개변수에 전부 값을 넣어 주는 경우 ###
greet("Alice", 25, "New York")

### 마지막 매개변수에 값을 넣지 않고 초기화 변수를 쓰고 싶은 경우 ###
# 함수 호출 시 그냥 넣지 않으면 됨. 
# (이때 뒤에 ,를 넣어도 상관 없음)
greet("Bob", 30)
greet("Bob", 30,)

## 이건 안됨 ##
greet("John", , "LA")

더 참고해볼 사이트

http://www.flowdas.com/blog/thread-safety-in-python/


본 후기는 정보통신산업진흥원(NIPA)에서 주관하는 <AI 서비스 완성! AI+웹개발 취업캠프 - 프론트엔드&백엔드> 과정 학습/프로젝트/과제 기록으로 작성 되었습니다.

profile
유후랄라 개발일기

0개의 댓글