Lock Free ObjectPool的C#實現 (對象池)

來源:互聯網
上載者:User

最近實現了一個LockFree的對象池

主要的想法是:

  1.複用構造出來的對象
  2.避免重複建立和銷毀對象對GC造成的壓力

  3.避免重複建立對象造成的資源消耗

最適合的情境是:

  1.構造對象很慢,並且需要構造很多個對象的情況

主要技術特徵:

  1. C#4.0的實現(可以降級到2.0)

  2. 內部沒有使用普通的lock,而是使用Lock Free的實現方式

  3. 將常用的取回對象的方式,換成委託運行, 這樣的話ObjectPool可以幫你自動將對象壓回隊列

  4. ObjectPool支援對象池上下限的設定(如果移除該功能效能還會提高很多!)

以下是實現代碼:

    /// <summary>
/// 對象池 (有上下限的版本..如果不要控制上限的話性還能好很多)
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class ObjectPool<T>
{
#region private Fields 為了調試方便 吧一些變數弄成了Public, 實際使用中請關掉
private int isTaked = 0;
private Queue<T> queue = new Queue<T>();
private Func<T> func = null;
private int currentResource = 0;
public int tryNewObject = 0;
private int minSize = 0;
private int maxSize = 0;
#endregion

#region private methods
private void Enter()
{
while (Interlocked.Exchange(ref isTaked, 1) != 0)
{
}
}
private void Leave()
{
Thread.VolatileWrite(ref isTaked, 0);
}
#endregion

/// <summary>
/// 構造一個對象池
/// </summary>
/// <param name="func">用來初始化對象的函數</param>
/// <param name="minSize">對象池下限</param>
/// <param name="maxSize">對象池上限</param>
public ObjectPool(Func<T> func, int minSize = 1, int maxSize = 5)
{
if (func == null)
{
throw new ArgumentNullException("func");
}
if (minSize < 0)
{
throw new ArgumentOutOfRangeException("minSize");
}
if (maxSize < 0)
{
throw new ArgumentOutOfRangeException("maxSize");
}
if (maxSize < minSize)
{
throw new ArgumentException("maxSize can not be less than minSize");
}

this.minSize = minSize;
this.maxSize = maxSize;
for (int i = 0; i < minSize; i++)
{
this.queue.Enqueue(func());
}

this.currentResource = minSize;
this.tryNewObject = minSize;
this.func = func;
}

/// <summary>
/// 從對象池中取一個對象出來,並執行, 執行完成以後會自動將對象放回池中
/// </summary>
/// <param name="action">一個可用的對象</param>
public void Run(Action<T> action)
{
if (action == null)
{
throw new ArgumentNullException("func");
}
T t = default(T);
try
{
Start:
if (Interlocked.Decrement(ref this.currentResource) < 0)
{
if (this.tryNewObject < this.maxSize)
{
Interlocked.Increment(ref this.tryNewObject);
t = func();
Interlocked.Increment(ref this.currentResource);
}
else
{
Interlocked.Increment(ref this.currentResource);
goto Start;
}
}
else
{
this.Enter();
t = this.queue.Dequeue();
this.Leave();
}

action(t);
}
finally
{
this.Enter();
this.queue.Enqueue(t);
this.Leave();
Interlocked.Increment(ref currentResource);
}
}

/// <summary>
/// 看看現在的Queue中有多少個資源,線程不安全...
/// </summary>
[Obsolete]
public int ResourceCountInQueue { get { return queue.Count(); } }
}

測試代碼如下:(注意測試代碼是4.0的)

       static void Main(string[] args)
{
//測試代碼
int length = 1 * 1000 * 1000;
Stopwatch sw = Stopwatch.StartNew();
ObjectPool<MD5> pool = new ObjectPool<MD5>(() =>
{
Thread.Sleep(1000);//類比緩慢的構造情況
return new MD5CryptoServiceProvider();
});

Parallel.For(0, length, p =>
{
pool.Run(md5 =>
{
md5.ComputeHash(Guid.NewGuid().ToByteArray());//類比一個運算情境
});
});
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine(length);
Console.WriteLine(pool.ResourceCountInQueue);
}

 

順便測試一下機器效能...這個代碼在我機器上大約要跑10秒鐘......- -#

 

歡迎大家指正~

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.