同步的概念
1. 多線程開發可能遇到的問題
假設兩個線程t1和t2都要對num=0進行增1運算,t1和t2都各對num修改10次,num的最終的結果應該為20。
但是由于是多線程訪問,有可能出現下面情況:
在num=0時,t1取得num=0。此時系統把t1調度為”sleeping”狀態,把t2轉換為”running”狀態,t2也獲得num=0。然后t2對得到的值進行加1并賦給num,使得num=1。然后系統又把t2調度為”sleeping”,把t1轉為”running”。線程t1又把它之前得到的0加1后賦值給num。這樣,明明t1和t2都完成了1次加1工作,但結果仍然是num=1。
~~~
from threading import Thread
import time
g_num = 0
def test1():
global g_num
for i in range(1000000):
g_num += 1
print("---test1---g_num=%d"%g_num)
def test2():
global g_num
for i in range(1000000):
g_num += 1
print("---test2---g_num=%d"%g_num)
p1 = Thread(target=test1)
p1.start()
# time.sleep(3) #取消屏蔽之后 再次運行程序,結果會不一樣,,,為啥呢?
p2 = Thread(target=test2)
p2.start()
print("---g_num=%d---"%g_num)
~~~
運行結果(可能不一樣,但是結果往往不是2000000):
~~~
---g_num=284672---
---test1---g_num=1166544
---test2---g_num=1406832
~~~
取消屏蔽之后,再次運行結果如下:
---test1---g_num=1000000
---g_num=1041802---
---test2---g_num=2000000
問題產生的原因就是沒有控制多個線程對同一資源的訪問,對數據造成破壞,使得線程運行的結果不可預期。這種現象稱為“線程不安全”。
2. 什么是同步
同步就是協同步調,按預定的先后次序進行運行。如:你說完,我再說。
"同"字從字面上容易理解為一起動作
其實不是,"同"字應是指協同、協助、互相配合。
如進程、線程同步,可理解為進程或線程A和B一塊配合,A執行到一定程度時要依靠B的某個結果,于是停下來,示意B運行;B依言執行,再將結果給A;A再繼續操作。
3. 解決問題的思路
對于本小節提出的那個計算錯誤的問題,可以通過線程同步來進行解決
思路,如下:
1. 系統調用t1,然后獲取到num的值為0,此時上一把鎖,即不允許其他現在操作num
2. 對num的值進行+1
3. 解鎖,此時num的值為1,其他的線程就可以使用num了,而且是num的值不是0而是1
4. 同理其他線程在對num進行修改時,都要先上鎖,處理完后再解鎖,在上鎖的整個過程中不允許其他線程訪問,就保證了數據的正確性