python 스 레 드 를 강제 적 으로 죽 이지 마 세 요.
python 스 레 드 를 강제 적 으로 죽 이려 고 하지 마 세 요.이것 은 서비스 디자인 에 있어 서 이성 에 맞지 않 습 니 다.다 중 스 레 드 는 작업 의 협력 과 병행 에 사 용 됩 니 다.강제 적 인 수단 으로 스 레 드 를 제거 하면 예상 치 못 한 bug 가 발생 할 확률 이 높 습 니 다. 한 가지 만 기억 하 세 요.잠 금 자원 은 스 레 드 가 종료 되 었 기 때문에 잠 금 자원 을 방출 하지 않 습 니 다!
우 리 는 두 가지 흔히 볼 수 있 는 예 를 들 수 있다.
1.A 라인 이 자 물 쇠 를 가 져 왔 습 니 다.그 는 강제 적 으로 제거 되 었 기 때문에 제때에 release()에서 자 물 쇠 를 방출 하지 못 했 습 니 다.그러면 모든 라인 이 자원 을 가 져 오 는 것 이 막 혔 습 니 다.이것 이 바로 전형 적 인 자물쇠 장면 입 니 다.
2.흔히 볼 수 있 는 생산 소비자 의 장면 에서 소비 자 는 미 션 대기 열 에서 임 무 를 얻 지만 해 킹 당 한 후에 하고 있 는 임 무 를 대기 열 에 잃 어 버 리 지 않 으 면 데이터 가 손실 된다.
다음은 자바 와 python 이 스 레 드 를 종료 하 는 방법 입 니 다.
자바 는 스 레 드 를 종료 할 수 있 는 세 가지 방법 이 있 습 니 다.
1.종료 표 지 를 사용 하여 스 레 드 를 정상적으로 종료 합 니 다.즉,run 방법 이 완 료 된 후에 스 레 드 가 종 료 됩 니 다.
2.stop 방법 을 사용 하여 스 레 드 를 강제로 종료 합 니 다(사용 을 추천 하지 않 습 니 다.stop 은 suspend,resume 과 마찬가지 로 예측 할 수 없 는 결과 가 발생 할 수 있 기 때 문 입 니 다).
3.interrupt 방법 으로 스 레 드 를 중단 합 니 다.
python 은 두 가지 방법 이 있 습 니 다.
1.태그 끝내기
2.ctypes 를 사용 하여 스 레 드 를 강제로 죽 입 니 다.
python 이 든 자바 환경 이 든 이상 적 인 스 레 드 종료 방법 은 스 레 드 를 스스로 자살 시 키 는 것 입 니 다.스 레 드 자살 이란 바로 당신 이 그 에 게 표지 판 을 주 는 것 입 니 다.그 는 스 레 드 에서 물 러 납 니 다.
다음은 python 스 레 드 를 정지 하 는 이상 상황 을 여러 가지 방법 으로 테스트 할 것 입 니 다.우 리 는 프로 세 스 의 모든 실행 스 레 드 를 봅 니 다. 프로 세 스 는 자원 을 제어 한 적 이 있 습 니 다.스 레 드 는 스케줄 러 로 사 용 됩 니 다.프로 세 스 가 실행 되 려 면 스 레 드 가 있어 야 합 니 다.기본 스 레 드 는 프로 세 스 의 pid 와 같 습 니 다.
ps -mp 31449 -o THREAD,tid
USER %CPU PRI SCNT WCHAN USER SYSTEM TID
root 0.0 - - - - - -
root 0.0 19 - poll_s - - 31449
root 0.0 19 - poll_s - - 31450
프로 세 스 의 모든 스 레 드 를 가 져 온 후,strace 를 통 해 31450 이 kill 이 필요 한 스 레 드 id 라 는 것 을 알 게 되 었 습 니 다.kill 이 필요 할 때 전체 프로 세 스 가 무 너 지 는 상황 이 발생 합 니 다.다 중 스 레 드 환경 에서 발생 하 는 신 호 는 전체 프로 세 스에 전달 되 는 것 입 니 다.일반적으로 모든 스 레 드 는 이 신 호 를 받 을 기회 가 있 습 니 다.프로 세 스 는 신 호 를 받 은 스 레 드 컨 텍스트 에서 신호 처리 함 수 를 실행 합 니 다.구체 적 으로 어떤 스 레 드 가 실행 되 는 지 알 수 없습니다.즉,신 호 는 이 프로 세 스 의 스 레 드 를 무 작위 로 보 내 는 것 이다.
strace -p <span style="font-size:14px;line-height:21px;">31450</span> Process <span style="font-size:14px;line-height:21px;">31450</span> attached - interrupt to quit
select(0, NULL, NULL, NULL, {0, 320326}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = ? ERESTARTNOHAND (To be restarted)
--- SIGTERM (Terminated) @ 0 (0) ---
Process <span style="font-size:14px;line-height:21px;">31450</span> detached
위 에 나타 난 문 제 는 사실 pthread 의 설명 과 일치 합 니 다.python 코드 에 signal 신호 처리 함 수 를 추가 한 후에 리 셋 함 수 는 전체 프로 세 스 의 종 료 를 방지 할 수 있 습 니 다.그러면 문제 가 발생 했 습 니 다.신호 함 수 를 통 해 어떤 스 레 드 를 제거 해 야 하 는 지 식별 할 수 없습니다.즉,특정한 스 레 드 를 정확하게 제거 할 수 없습니다.당신 은 신 호 를 31450 스 레 드 id 에 보 냈 지만 신호 수리 자 는 소속 프로 세 스 의 모든 것 입 니 다.또한 신호 처리 함수 에 전 달 된 매개 변 수 는 신호 수 와 신호 stack 일 뿐 있 으 나 마 나 합 니 다.신호 처 리 를 추가 하면 프로 세 스 를 종료 하지 않 습 니 다.
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = ? ERESTARTNOHAND (To be restarted)
--- SIGTERM (Terminated) @ 0 (0) ---
rt_sigreturn(0xffffffff) = -1 EINTR (Interrupted system call)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
외부 알림 에서 특정한 스 레 드 를 죽 이려 면 rpc 서 비 스 를 사용 하거나 다른 방식 으로 통신 할 수 있 습 니 다.signal 신 호 는 더 많은 정 보 를 전달 할 수 없 기 때 문 입 니 다.python 의 스 레 드 는 시 뮬 레이 션 이 아니 라 실제 커 널 스 레 드 입 니 다.커 널 은 pthread 방법 을 호출 하지만 Python 상층 부 는 스 레 드 를 닫 는 방법 을 제공 하지 않 았 습 니 다.이것 은 우리 가 스스로 파악 해 야 합 니 다.이벤트 나 사용자 정의 플래그 위 치 를 사용 하 는 방법 을 강력 히 추천 합 니 다.스 레 드 를 강제로 죽 이려 면 python ctypes PyThreadState SetAsyncExc 방법 으로 강제 종료 할 수 있 습 니 다.이 는 실행 중인 python 서비스 에 영향 을 주지 않 습 니 다.
이 함수 의 실현 원 리 는 비교적 간단 하 다.사실은 python 가상 컴퓨터 에서 표시 위 치 를 만 든 다음 에 가상 컴퓨터 에서 이상 을 실행 하여 스 레 드 를 취소 하고 가상 기 회 는 try cache 를 잘 만들어 준다.외부 에서 python 의 한 스 레 드 를 죽 이지 마 세 요.ctypes 를 통 해 스 레 드 id 를 찾 을 수 있 지만 직접 kill 하면 전체 프로 세 스 를 처리 할 수 있 습 니 다.
아래 코드 는 ctypes 로 스 레 드 를 죽 이 는 사례 입 니 다.사용 하 는 것 을 추천 하지 않 습 니 다.너무 거 칠 기 때 문 입 니 다.
import ctypes
def terminate_thread(thread):
if not thread.isAlive():
return
exc = ctypes.py_object(SystemExit)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
ctypes.c_long(thread.ident), exc)
if res == 0:
raise ValueError("nonexistent thread id")
elif res > 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
PyThreadState 소스 코드 를 간단하게 살 펴 보 겠 습 니 다.한 마디 로 스 레 드 의 이상 모드 를 촉발 합 니 다.관심 있 는 사람 은 python pystate.c 의 디자인 을 읽 고 유 튜브 의 일부 동 영상 과 함께 공유 할 수 있 습 니 다.
int
PyThreadState_SetAsyncExc(long id, PyObject *exc) {
PyInterpreterState *interp = GET_INTERP_STATE();
...
HEAD_LOCK();
for (p = interp->tstate_head; p != NULL; p = p->next) {
if (p->thread_id == id) {
id, , head_mutex。
PyObject *old_exc = p->async_exc;
Py_XINCREF(exc); #
p->async_exc = exc; # exc
HEAD_UNLOCK();
Py_XDECREF(old_exc); # ,
...
return 1; #
}
}
HEAD_UNLOCK();
return 0;
}
원생 poix pthread 는 ptread 를 사용 할 수 있 습 니 다.cancel(tid)은 메 인 스 레 드 에서 하위 스 레 드 를 끝 냅 니 다.그러나 Python 의 스 레 드 라 이브 러 리 는 이렇게 하 는 것 을 지원 하지 않 습 니 다.이 유 는 우리 가 하나의 스 레 드 를 강제로 끝내 서 는 안 되 기 때 문 입 니 다.그러면 많은 위험 을 가 져 올 것 입 니 다.이 스 레 드 를 스스로 끝내 야 합 니 다.그래서 Python 에서 추천 하 는 방법 은 하위 스 레 드 에서 하나의 표지 위 치 를 순환 적 으로 판단 하고 메 인 스 레 드 에서 이 표지 위 치 를 바 꾸 는 것 입 니 다.하위 스 레 드 는 표지 위치 가 바 뀌 면 자신 을 끝 냅 니 다.이 논리 와 유사 합 니 다:
def consumer_threading():
t1_stop= threading.Event()
t1 = threading.Thread(target=thread1, args=(1, t1_stop))
t2_stop = threading.Event()
t2 = threading.Thread(target=thread2, args=(2, t2_stop))
time.sleep(duration)
#stop the thread2
t2_stop.set()
def thread1(arg1, stop_event):
while(not stop_event.is_set()):
#similar to time.sleep()
stop_event.wait(time)
pass
def thread2(arg1, stop_event):
while(not stop_event.is_set()):
stop_event.wait(time)
pass
간단 한 정 리 는 ctypes 의 pystats 로 스 레 드 를 제어 할 수 있 지만 이런 거 친 중단 스 레 드 방법 은 불합리 합 니 다.자살 모드 를 선택 하 세 요!만약 당신 의 스 레 드 가 io 차단 이 발생 하고 있다 면 사건 을 판단 하지 못 하면 어떻게 합 니까?당신 의 프로그램 은 최적화 되 어야 합 니 다.적어도 네트워크 io 층 에 서 는 주동 적 인 timeout 이 있어 야 합 니 다.계속 막 히 지 않도록 해 야 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로마 숫자를 정수로 또는 그 반대로 변환그 중 하나는 로마 숫자를 정수로 변환하는 함수를 만드는 것이었고 두 번째는 그 반대를 수행하는 함수를 만드는 것이었습니다. 문자만 포함합니다'I', 'V', 'X', 'L', 'C', 'D', 'M' ; 문자열이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.