2011-11-21 83 views
8

我在多線程可訪問的Django會話中存儲字典。所有線程都可以更新該字典,線程也可以從字典中獲取值以運行該進程。我想知道Django Session是線程安全的還是我必須使用鎖或信號量?Django會話線程安全嗎?

典型的例子:

Thread1: 
threadDict = request.session.get('threadDict', None) 
if threadDict['stop']: 
    #break the for loop exit the thread 
else: 
    #do some processing and update some values in thread dictionary 
    threadDict['abc'] = 0 
    request.session['threadDict'] = threadDict (Point1) 

def someFunction(): 
    #this function is used to send stop signal to thread 
    threadDict = request.session.get('threadDict', None) 
    threadDict['stop'] = True 
    request.session['threadDict'] = threadDict (Point2) 

是否有機會,當它更新Point1在會議Point2更新線程字典剛過也更新它,然後我stop退出線程丟失。

更多信息

AJAX請求開始四個線程,其下載採樣來自4個不同的網址。爲什麼我使用線程?因爲我想向用戶展示哪些樣本目前正在下載以及哪些樣本已經下載。所有線程將在會話中的字典中更新其狀態。線程啓動後,我每兩秒鐘發出一次ajax請求,並從會話中取出字典並讀取線程的當前狀態。但是這個想法失敗了,因爲線程獨立於請求和會話。每個ajax請求都有它的會話,但是我不能將該會話傳遞給線程,因爲當它們一旦開始時,它們獨立於世界其他地方(可能我可以傳遞它,但是我可能無法通過它,因爲處理正在由線程)。所以要解決這個問題,我選擇緩存框架而不是會話。因爲緩存可以從任何地方訪問。線程將它們的狀態存儲在字典中,並放回緩存中,每隔兩秒鐘我就從緩存中取出字典並讀取狀態。根據我的經驗緩存還有一件事情不是線程安全的。所以對於四個線程,我單獨使用了四個字典。

回答

6

request.session返回的對象將是每個請求的新對象,訪問同一個存儲。此外,它們在請求時從存儲器加載並在響應時間保存。因此,如果您希望將信息從長時間運行的線程傳輸到另一個請求,則需要手動將其保存在長時間運行的線程中。不幸的是,這會導致對同一會話數據丟失的修改。

會話在某種意義上是線程安全的。你不會以這種方式打破口譯員。您的請求會將會話數據視爲第一次訪問時的快照,保存時會覆蓋自那一刻起降落的所有更改。因此會話狀態將保持一致,但某些請求的修改可能會丟失。

實際上,該屬性幾乎適用於任何框架 - 任何會話/緩存/可能在多個進程之間共享的一些其他存儲都不可能提供對內部存儲的對象的修改,而不會覆蓋某人的更改。

+0

如果我沒有記錯,您可以編輯您的問題並將信息添加到它。 – Tanriol

+0

好的,謝謝我在問題中增加了更多細節。 –

0

由於global interpreter lock的原因,Python中的基本類型通常是線程安全的。在某些情況下(例如,在執行I/O時)釋放此鎖以允許其他線程訪問。這意味着您(應用程序)必須在可能釋放GIL的呼叫之間保持一致的狀態。這種方法的例子是阻塞套接字操作。

+0

有沒有辦法訪問Django會話中的某些功能,而不使用'request.session'我想直接訪問會話? –

+0

爲什麼你不想使用request.session? – Krumelur

+0

我想將線程的狀態存儲在某個地方,因爲線程一旦啓動,我無法再次傳遞請求,一旦我啓動進程,我做ajax請求來檢查狀態,該狀態將存儲在會話中的字典知道什麼是當前的線程狀態。所以我想如果有任何方法直接訪問會話,以便線程可以存儲它的狀態? –

0

我不確定django是線程安全的。 例如,如果您使用Apache + mod_wsgi配置,並且每個進程有多個線程,則django/core/urlresolvers.py不是線程安全的。 但他們努力去做。 有些票在Django票務系統上15849

2

Django會話是在請求處理開始時提取的字典,並在其末尾保存[source]。 因此,如果您對其執行並行更改,那麼其中一項更改將佔上風。但通常情況下,人類用戶不能執行這種並行操作,而且業務還在繼續。

現在,我不太明白你的例子,但它看起來像你只是試圖濫用會話字典。我已經開發了很多基於Django的網站,我在Django本身中遇到了一些與限制或錯誤相關的問題,但仍然搞亂了來自多個線程的會話詞典,看起來像我的一個教科書示例濫用會議......

也許我們可以找出解決方案,當你寫更多關於你想要實現的東西?

0

正如@Krumelur所提到的,由於全局中斷者鎖(GIL),Python線程不會同時運行 - 這是一個缺陷,而不是一個功能,所以不要依賴它。

當前的解決方法是使用multiprocessing module創建子流程。您可以使用Process實例的is_alive()函數檢查並查看是否正在運行一個子進程。請參閱juicy details的文檔。