2010-01-28 129 views
4

在python中,我定義了一個全局變量,它可以被不同的線程讀/遞增。由於GIL,這會導致問題而不使用任何種類的鎖定機制?Python GIL和全局變量

+0

您是否在談論使用「線程」模塊的實現?在這種情況下,您應該使用提供的鎖定機制:請參閱http://docs.python.org/library/threading.html – avpx 2010-01-28 19:18:57

回答

3

是的,沒有鎖定的多線程幾乎總是會導致問題,有或沒有GIL。

+2

請注意,GIL不適用於保護您的應用程序數據;它僅用於保護一些Python內部結構,如Python對象的引用計數。你仍然必須鎖定你的結構。確切地說, – 2010-01-28 19:42:12

+1

。 GIL保護Python本身,但它沒有做任何事情來保護你。 – 2010-01-29 02:34:23

+1

當然,絕大多數Python執行引擎甚至不具有* GIL。 – 2010-01-29 04:39:37

6

GIL只要求解釋器在另一個線程可以接管之前完全執行單個字節碼指令。但是,沒有理由認爲增量操作是單個指令。例如:

>>> import dis 
>>> dis.dis(compile("x=753","","exec")) 
    1   0 LOAD_CONST    0 (753) 
       3 STORE_NAME    0 (x) 
       6 LOAD_CONST    1 (None) 
       9 RETURN_VALUE 
>>> dis.dis(compile("x+=1","","exec")) 
    1   0 LOAD_NAME    0 (x) 
       3 LOAD_CONST    0 (1) 
       6 INPLACE_ADD 
       7 STORE_NAME    0 (x) 
      10 LOAD_CONST    1 (None) 
      13 RETURN_VALUE 

正如你可以看到,即使這些簡單的操作比單字節碼指令多。因此,無論何時在線程之間共享數據,您必須使用單獨的鎖定機制(例如threading.lock)以保持數據一致性。

+2

Ouch。我的意思是,3個upvotes,沒有人注意到'dis.dis(「x = 753」)'輸出?我更正了代碼。 – tzot 2010-02-01 21:01:41

+0

下面是一個例子,我應該更多地關注我正在寫的東西 - 謝謝:)。此外,它更清楚地顯示了該點 - 加載該值後,再次存儲該值之前有*個*指令。 – 2010-02-01 21:23:13

+0

這甚至不是100%真實的。字節碼(幾乎任何)實際上可以通過'__getitem__'或'__add__'或任何其他場景調用更多的Python代碼。然後你最終通過一個字節碼中途交換線程。 – fijal 2012-08-31 16:33:40