併發操作的資料安全問題

2021-09-01 23:49:54 字數 2416 閱讀 6619

多執行緒執行環境下肯定存在併發,會存在乙個物件被多個執行緒同時操作(對同一資料的訪問)的情況,這樣如果不加以控制,很容易存在資料安全問題。

下面以乙個銀行轉賬的例子來說明併發可能存在的問題:

模擬賬戶–account類:

public class account 

public string getname()

public void setname(string name)

public double getmoney()

public void setmoney(double money)

}

模擬銀行–bank類:

public class bank  else 	}	

/*** 列印餘額

* @param account 賬戶

*/public void display(account account)

}

轉賬執行緒–transferrunnable類:

/**

* 轉賬執行緒

* @author 朋

* */

public class transferrunnable implements runnable catch (interruptedexception e) }

public transferrunnable (bank bank,account fromaccount,account toaccount,double money)

}

列印餘額執行緒–displayrunnable:

package com.demo;

/** * 列印餘額執行緒

* @author 朋

* */

public class displayrunnable implements runnable

@override

public void run() catch (interruptedexception e)

}}

測試–test類:

public class test 

}}

執行結果(部分):

該例子模擬了zhangsan和lisi兩個賬戶在併發得進行轉賬和列印餘額的操作,其中呼叫了thread.sleep()方法模擬了現實中地延遲。從執行結果可以看到,其資料是混亂的,比如上圖第七行和第八行,zhangsan向lisi轉賬50元後,lisi查詢到的餘額居然是0元,zhnagsan查詢到的餘額是200元,隨著lisi又向zhangsan轉賬100元。

正常情況下,應該是上圖執行結果第七行zhangsan向lisi轉賬50元後,lisi的餘額為100元,zhangsan的餘額也為100元。隨後lisi向zhangsan轉賬100元,此時lisi的餘額才為0,zhangsan的餘額才為200。

上述例子在併發操作時,對相同資料進行訪問導致了資料的不一致問題,一般情況下,資料不一致問題有:丟失修改、不可重複讀、髒讀。

假如zhangsan和lisi餘額都為100,此時有兩個執行緒a和b同時發起zhangsan向lisi轉賬50元的操作。

t1時刻執行緒a將zhangsan向lisi轉賬50的結果(zhangsan:100-50元,lisi:100+50元)寫入zhangsan和lisi的賬戶;

t2時刻執行緒b將zhangsan向lisi轉賬50的結果(zhangsan:100-50元,lisi:100+50元)寫入zhangsan和lisi的賬戶。

兩個執行緒都執行成功,正常情況下zhangsan的餘額應該為0元,lisi的餘額為200元。但是zhangsan的金額僅轉出了50元到lisi,很明顯有乙個執行緒的資料修改操作丟失了。

假如某時刻zhangsan和lisi餘額都為100,此時有乙個執行緒a發起zhangsan向lisi轉賬50元的操作,結果為zhangsan的餘額為50元,lisi的餘額為150元。

另外乙個時刻zhangsan和lisi餘額也都為100,此時執行緒a再次發起zhangsan向lisi轉賬50元的操作,這時另外乙個執行緒也發起lisi向zhangsan轉賬30元的操作,結果為zhangsan的餘額為80元,lisi的餘額為120元。

同一執行緒a對同一組資料的相同運算結果不同,顯然與事實不符,這就是不可重複讀。

假如某時刻zhangsan和lisi餘額都為100,執行緒a對zhangsan發起餘額查詢操作,同時執行緒b發起zhangsan向lisi轉賬50元的操作,此時執行緒a查詢到的是100元,而此時zhangsan實際上已經轉出了50元。

要解決併發帶來的資料的安全問題,就必須對執行緒進行併發控制。

併發安全問題

守護程序是指乙個程序守護另乙個程序 例如a是b的守護程序b如果結束了a也會隨之結束 def task name print s is running name time.sleep 3 if name main obj process target task,args egon obj.daemon...

map併發安全問題

go語言官方部落格中 go maps in action 有說明 map型別不是併發安全的 它沒有定義當你同時讀取和寫入map時發生的情況,如果你需要在併發執行的goroutine中讀取和寫入map,那麼訪問時必須通過某種同步機制來調解。讀寫鎖 sync.rwmutex 是用來保護map的一種常用方...

高併發執行緒安全問題

高併發執行緒 1 當多個執行緒訪問同乙個共享物件時,就是高併發執行緒。如,天貓雙十一等。因為執行緒的排程是搶占式的,當乙個執行緒在訪問共享資料 可以是多行 也可以是成員變數 時,其他執行緒也參與了該共享資料的運算,就會造成資料汙染,即執行緒安全 a 可見性 當多條執行緒在運算同一共享資料時,某條執行...