【Nim】執行緒記憶體模型
阿新 • • 發佈:2018-12-09
在Nim的設計中,每一個執行緒都有自己一個獨立的heap,這意味著在多個執行緒之間不能引用同一個變數,帶來的好處是不會出現競態條件(race condition),壞處也很明顯,多執行緒之間無法共享變數。
讓我們來看個簡單的例子感受一下。為了引入多執行緒,我安裝了第三方庫winim(幾乎涵蓋了所有的windows api,非常棒)
import winim/lean echo "Main Thread: ", GetCurrentThreadId() type MyObj = ref object x: int proc free(this: MyObj) = this.x = -1 echo "Free" proc builder(): MyObj = new(result, free) result.x = 5 var obj = builder() echo "Main Thread: x = ", obj.x proc threadProc(param: LPVOID): DWORD {.stdcall.} = echo "Child Thread: ", GetCurrentThreadId() var b = obj # 引用主執行緒的變數 echo "Child Thread: x = ", b.x Sleep(3000) # 在這期間obj已經被主執行緒釋放了 echo "Child Thread: x = ", b.x CreateThread(nil, 0, LPTHREAD_START_ROUTINE(threadProc), nil, 0, nil) # 暫停一下,要不然執行緒還沒執行 Sleep(1000) obj = nil GC_fullCollect() Sleep(5000) echo "Bye"
執行結果如下:
Main Thread: 7364 Main Thread: x = 5 Child Thread: 10440 Child Thread: x = 5 Free Child Thread: x = -1 Bye
在主執行緒中手動回收物件後,特地將成員變數x置為-1,然後子執行緒前後兩次輸出結果不同。
正是因為主執行緒感知不到子執行緒引用了其維護的變數,導致主執行緒在GC後,子執行緒引用的記憶體區域已經失效,而子執行緒也不知道主執行緒將變量回收了,引發了資料異常。
相關資料: