리스트는 스레드 세이프입니까?
리스트와 큐 대신 여러 스레드를 가진 큐를 사용하는 것이 권장되는 경우가 많습니다..pop()리스트가 스레드 세이프가 아니기 때문입니까, 아니면 다른 이유 때문입니까?
리스트 자체는 스레드 세이프입니다.CPython에서는 GIL이 동시 액세스로부터 보호하며, 다른 구현에서는 목록 구현에 세밀한 잠금 또는 동기화된 데이터 유형을 사용하도록 주의합니다.그러나 목록 자체는 동시에 액세스하려고 해도 손상되지 않지만 목록의 데이터는 보호되지 않습니다.예를 들어 다음과 같습니다.
L[0] += 1
다른 스레드가 같은 동작을 하는 경우 L[0]이 실제로1개 증가하는 것은 보증되지 않습니다.왜냐하면+=원자적인 조작이 아닙니다.(Python에서의 조작은 실제로는 거의 없습니다.대부분이 임의의 Python 코드를 호출할 수 있기 때문입니다.)보호되지 않은 목록만 사용할 경우 레이스 조건으로 인해 잘못된 항목을 가져오거나 삭제할 수 있으므로 큐를 사용해야 합니다.
토마스의 훌륭한 답변의 요점을 명확히 하기 위해 언급되어야 한다.append() 스레드 세이프
이는 데이터를 쓰기 위해 한 번 가면 읽히는 데이터가 같은 위치에 있을 염려가 없기 때문입니다.그append()작업은 데이터를 읽지 않고 목록에만 데이터를 씁니다.
이 리스트는 포괄적이면서도 철저한 예는 아닙니다.list작업 및 스레드 세이프 여부를 확인합니다.에 대한 답변을 듣고 싶습니다.obj in a_list여기서 언어를 구성합니다.
최근 한 스레드에서 목록에 계속 추가해 아이템을 루프하고 아이템이 준비되었는지 확인해야 하는 경우가 있었습니다.이 경우는 AsyncResult로 되어 있고, 준비된 경우에만 리스트에서 삭제했습니다.문제를 명확하게 나타내는 예를 찾을 수 없습니다.한 스레드 내의 리스트에 계속 추가하고 다른 스레드 내의 같은 리스트에서 연속적으로 삭제하는 예를 다음에 나타냅니다.결함 있는 버전은 적은 수치로 쉽게 실행되지만 숫자는 충분히 크고 몇 번 실행되면 오류가 나타납니다.
결함이 있는 버전
import threading
import time
# Change this number as you please, bigger numbers will get the error quickly
count = 1000
l = []
def add():
for i in range(count):
l.append(i)
time.sleep(0.0001)
def remove():
for i in range(count):
l.remove(i)
time.sleep(0.0001)
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=remove)
t1.start()
t2.start()
t1.join()
t2.join()
print(l)
오류 발생 시 출력
Exception in thread Thread-63:
Traceback (most recent call last):
File "/Users/zup/.pyenv/versions/3.6.8/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/Users/zup/.pyenv/versions/3.6.8/lib/python3.6/threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "<ipython-input-30-ecfbac1c776f>", line 13, in remove
l.remove(i)
ValueError: list.remove(x): x not in list
잠금을 사용하는 버전
import threading
import time
count = 1000
l = []
lock = threading.RLock()
def add():
with lock:
for i in range(count):
l.append(i)
time.sleep(0.0001)
def remove():
with lock:
for i in range(count):
l.remove(i)
time.sleep(0.0001)
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=remove)
t1.start()
t2.start()
t1.join()
t2.join()
print(l)
산출량
[] # Empty list
결론
이전 답변에서 설명한 바와 같이 리스트에서 요소를 추가하거나 팝하는 동작 자체는 스레드 세이프하지만 스레드 세이프가 아닌 것은 스레드에 추가하고 다른 스레드에 팝하는 경우입니다.
언급URL : https://stackoverflow.com/questions/6319207/are-lists-thread-safe
'source' 카테고리의 다른 글
| PHP에서 upload_max_filesize 변경 (0) | 2023.01.15 |
|---|---|
| PHPMYADMIN에서 group_concat을 사용하면 결과가 [BLOB - 3B]로 표시됩니다. (0) | 2023.01.15 |
| Python: 예외를 무시하고 계속 진행하려면 어떻게 해야 합니까? (0) | 2023.01.15 |
| convert_tz가 null을 반환합니다. (0) | 2023.01.15 |
| Python 스크립트를 프로파일하려면 어떻게 해야 하나요? (0) | 2023.01.15 |