在同一程式中執行多個執行緒本身不會導致問題,
問題只有在一或多個執行緒向這些資源做了寫操作時才有可能發生,只要資源沒有發生變化,多個執行緒讀取相同的資源就是安全的。
多執行緒同時執行下面的**可能會出錯:
1
public
class
counter
6
}
想象下執行緒a和b同時執行同乙個counter物件的add()方法,我們無法知道作業系統何時會在兩個執行緒之間切換。jvm並不是將這段**視為單條指令來執行的,而是按照下面的順序:
從記憶體獲取 this.count 的值放到暫存器觀察執行緒a和b交錯執行會發生什麼,兩個執行緒分別加了2和3到count變數上,兩個執行緒執行結束後count變數的值應該等於5。然而由於兩個執行緒是交叉執行的,兩個執行緒從記憶體中讀出的初始值都是0。然後各自加了2和3,並分別寫回記憶體。最終的值並不是期望的5,而是最後寫回記憶體的那個執行緒的值,上面例子中最後寫回記憶體的是執行緒a,但實際中也可能是執行緒b。如果沒有採用合適的同步機制,執行緒間的交叉執**況就無法預料。將暫存器中的值增加value
將暫存器中的值寫回記憶體
競態條件(race condition):當兩個執行緒競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態條件。導致競態條件發生的**區稱作臨界區。上面的add方法就是臨界區。可以這樣理解:臨界區的訪問需要的是互斥。
區域性變數
區域性的物件引用
區域性的物件引用
01
public
void
somemethod()
08
09
public
void
method2(localobject localobject)
樣例中localobject物件沒有被方法返回,也沒有被傳遞給somemethod()方法外的物件。每個執行somemethod()的執行緒都會建立自己的localobject物件,並賦值給localobject引用。因此,這裡的localobject是執行緒安全的。事實上,整個somemethod()都是執行緒安全的。即使將localobject作為引數傳給同乙個類的其它方法或其它類的方法時,它仍然是執行緒安全的。當然,如果localobject通過某些方法被傳給了別的執行緒,那它就不再是執行緒安全的了.
物件成員
物件成員儲存在堆上。如果兩個執行緒同時更新同乙個物件的同乙個成員,那這個**就不是執行緒安全的。下面是乙個樣例:
1
public
class
notthreadsafe
7
}
如果兩個執行緒同時呼叫同乙個notthreadsafe
例項上的add()方法,就會有競態條件問題。例如:
01
notthreadsafe sharedinstance =
new
notthreadsafe();
02
03
new
thread(
new
myrunnable(sharedinstance)).start();
04
new
thread(
new
myrunnable(sharedinstance)).start();
05
06
public
class
myrunnable
implements
runnable
12
13
public
void
run()
16
}
注意兩個myrunnable共享了同乙個notthreadsafe物件。因此,當它們呼叫add()方法時會造成競態條件。
當然,如果這兩個執行緒在不同的notthreadsafe例項上呼叫call()方法,就不會導致競態條件。下面是稍微修改後的例子:
1
new
thread(
new
myrunnable(
new
notthreadsafe())).start();
2
new
thread(
new
myrunnable(
new
notthreadsafe())).start();
現在兩個執行緒都有自己單獨的notthreadsafe物件,呼叫add()方法時就會互不干擾,再也不會有競態條件問題了。所以非執行緒安全的物件仍可以通過某種方式來消除競態條件。
總結:
1.區域性變數中的基本資料型別(8種)永遠是執行緒安全的。
2.區域性變數中的物件型別只要不會被其他執行緒訪問到,也是執行緒安全的。
3.乙個物件例項被多個執行緒同時訪問時,他的成員變數就可能是執行緒不安全的。
多執行緒共享資源案例
最近研究了一下多執行緒,主要針對於多執行緒共享同一資源,和多執行緒執行各自的資源 其實主要要就是搞清楚資源的含義 你要操作什麼,什麼就是執行緒的資源!1.先說一下多執行緒執行各自的資源 執行各自的資源從字面意思就可以看出來執行緒執行的資源互不干涉,各自執行各自的。案例如下 package testt...
初學多執行緒(一) 保護共享資源
1.共享資源未被保護,被多個執行緒並行訪問,會發生資源分配上的衝突,兩種方法保護共享資源 ps 共享資源像靜態類中的字段,方法 how to protect shared resources from concurrent access?1.使用 interlocked.increment 字段 在...
ios 多執行緒訪問共享資源
什麼是共享資源,一塊資源可能會被多個執行緒去共享,也就是多個執行緒可能會去訪問同一塊資源,也就是共享這一塊資源。比如說多執行緒去訪問同乙個物件,同乙個變數,同乙個檔案。當多個執行緒訪問同一塊資源的時候,很容易引發資料的錯亂和資料的安全問題。這個時候我們在乙個執行緒在訪問那塊資源的時候,我們需要把它個...