2018 11 07日記 概覽 今日立冬, 信息時代帶來的焦躁讓學習無法深入, 所以打算以寫日記的形式戒掉焦躁, 重拾醉心學習的狀態. Synchronized與SyncRoot技術同步線程數據 Serializable特性作用 RPC(遠程方法調用) 數據同步 在多個線程中共用數據, 很容易出現 ...
2018-11-07日記
概覽
今日立冬, 信息時代帶來的焦躁讓學習無法深入, 所以打算以寫日記的形式戒掉焦躁, 重拾醉心學習的狀態.
- Synchronized與SyncRoot技術同步線程數據
- Serializable特性作用
- RPC(遠程方法調用)
數據同步
在多個線程中共用數據, 很容易出現
爭用條件
和死鎖
爭用條件(RaceCondition)
設想如下代碼和步驟:
- 第一個線程程式執行到
if
語句, 假設此時_state
等於5, 條件為真 - 進入
if
語句之後, 它就被其他線程搶占, 調度器運行另一個線程 - 在另一個線程中某些代碼將
_state
的值改變為6
- 第一個線程再次被調度, 此時
_state
等於6
, 在執行完_state++
語句後,_state
將等於7 - 提示: 實際上
_state++
的操作將從記憶體中獲取值,給該值增加1
, 然後再寫回記憶體. 這些操作都可能被線程調度器打斷, 造成線程不安全!
public void ChangeState()
{
if (_state == 5)
{
_state++;
}
}
解決方法是給_state
對象加鎖, 將鎖定對象設置為線程安全對象, 一個線程鎖住了_state
對象, 其他線程就必須等待該鎖定解除.
但是_state
是值對象
, 不是引用對象
, lock
只能鎖住引用對象
, 因為鎖住一個值的副本毫無意義. 那麼就需要用一個對象來同步.代碼如下:
public class StateObject
{
private int _state = 5;
private object sync = new object();
public void ChangeState()
{
lock (sync)
{
if (_state == 5)
{
_state++;
}
}
}
}
死鎖(Deadlock)
過多的鎖會導致線程都再等待對方解除鎖定, 出現死鎖. 所以再程式設計一開始就需要考慮到死鎖問題, 設計好鎖定順序和鎖定超時時間.
Synchronized與SyncRoot技術
再.net集合類型中, 比如
Hashtable
和ArrayList
都有Synchronized
靜態方法和SyncRoot
實力方法. 返回一個線程安全的SyncHashtable
對象, 這個對象中的方法, 比如Add
都會鎖定SyncRoot
以確保線程安全的操作集合.
namespace SynchronizationSamples
{
public class Demo
{
public virtual bool IsSynchronized => false;
public virtual void DoThis() {}
public virtual void DoThat() {}
public static Demo Synchronized(Demo d)
{
if (!d.IsSynchronized)
{
return new Synchronized(d);
}
return d;
}
}
// 同步版本
private class SynchronizedDemo: Demo
{
public override bool IsSynchronized => true;
private object _syncRoot = new object();
private Demo _d;
public SynchronizedDemo(Demo d)
{
_d = d;
}
public override void DoThis()
{
lock (_syncRoot)
{
_d.DoThis();
}
}
public override void DoThat()
{
lock (_syncRoot)
{
_d.DoThat();
}
}
}
}
SyncRoot
確保再一個實例中, 不管再代碼的任何位置調用, 返回的都是同一個對象, 它是唯一的.
public virtual object SyncRoot
{
get
{
if (this._syncRoot == null)
{
// Interlocked為多個線程共用的變數提供原子操作, 原子操作就是單線程操作
Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
}
return this._syncRoot;
}
}
Serializable特性和RPC
todo: #1 今天太晚, 沒時間再寫了, 以後補上.
延申閱讀
- 併發集合類型