사실, 아니요, 각 스레드는 정확하게 인터프리터의 새 스레드입니다.
OS에서 관리하는 실제 스레드이며 Python 가상 머신 내에서 Python 코드 용으로 내부 관리 스레드가 아닙니다.
GIL은 OS 기반 스레딩이 Python 객체를 엉망으로 만드는 것을 방지하기 위해 필요합니다.
하나의 CPU에는 스레드가 있고 다른 CPU에는 스레드가 있다고 상상해보십시오. 어셈블리로 작성된 순수 병렬 스레드. 둘 다 동시에 레지스트리 값을 변경하려고합니다. 전혀 바람직한 상황이 아닙니다. 동일한 메모리 위치에 액세스하기위한 어셈블리 명령어는 언제 어디서 이동할 것인지에 대해 궁금해합니다. 결국 그러한 행동의 결과는 세분화 오류로 쉽게 이어질 수 있습니다. 글쎄, 우리가 C로 작성한다면, C는 그 부분을 제어한다. 그래서 이것은 C 코드에서 일어나지 않는다. GIL은 C 레벨에서 파이썬 코드에서도 똑같습니다. 따라서 Python 객체를 구현하는 코드는이를 변경할 때 원 자성을 잃지 않습니다. 다른 스레드가 일부 요소를 제거했기 때문에 다른 스레드에서 아래로 이동 한 목록에 값을 삽입하는 스레드를 상상해보십시오. GIL이 없으면 충돌이 발생합니다.
GIL은 스레드 내에서 코드의 원 자성에 대해 아무런 성과가 없습니다. 내부 메모리 관리를위한 것입니다.
deque()와 같은 스레드 안전 오브젝트가있는 경우에도 추가 잠금없이 둘 이상의 조작을 동시에 수행하는 경우 그 중간에 삽입 된 다른 스레드에서 결과를 얻을 수 있습니다. 그리고 웁스, 문제가 발생합니다!
하나의 스레드가 스택에서 객체를 가져 와서 그것에 대해 무언가를 검사하고, 조건이 올바르다면 말하십시오.
stack = [2,3,4,5,6,7,8]
def thread1():
while 1:
v = stack[0]
sleep(0.001)
if v%2==0: del stack[0]
sleep(0.001)
물론 이것은 바보 같으며이를 피하려면 stack.pop (0)을 사용해야합니다. 그러나 이것은 하나의 예입니다.
그리고 각 스택에 스택 0을 추가하는 다른 스레드가 있습니다.002초 : 이제
def thread2():
while 1:
stack.insert(0, stack[-1]+1)
sleep(0.002)
당신이 할 경우 : thread2는() thread1 사이에 정확히에서 새 항목을 쌓아하려고 할 경우, 가능성이 있지만
이
thread(thread2,())
sleep(1)
thread(thread1,())
(순간이있을 것이다)의 검색 및 삭제. 따라서 thread1()은 검사중인 항목 대신 새로 추가 된 항목을 제거합니다. 결과는 우리의 바램을 따르지 않습니다. 그래서 GIL은 스레드에서 수행중인 작업을 제어하지 않습니다. 스레드는 더 기본적인 의미에서 서로에게 무엇을하고 있는지를 제어합니다.
일부 이벤트 티켓 구매를 위해 서버를 작성했다고 가정 해보십시오. 두 명의 사용자가 연결되어 동일한 티켓을 동시에 구매하려고합니다. 조심하지 않으면 사용자는 다른 사람 위에 앉아서 끝낼 수 있습니다.
스레드 안전 개체는 작업을 수행하는 개체이며 첫 번째 작업이 완료 될 때까지 다른 작업을 수행 할 수 없도록합니다.
예를 들어 한 스레드에서 deque()를 반복하면서 다른 스레드가 무언가를 추가하려고하면 첫 번째 스레드가 반복 될 때까지 append()가 차단됩니다. 이것은 스레드로부터 안전합니다.
일부 작업에서는 동기화 할 수있는 여러 명령어가 필요합니다. Python을 다른 스레드에서 해석 할 수 있습니다. GIL은 결코 파이썬 프로그램을 결코 동기화하지 않습니다. asyncio와는 아무런 관련이 없습니다. - 단지 파이썬 객체가 파이썬 레벨이 아닌 C 레벨에서 쓰레드에 안전하다는 것을 확인합니다. –