-1
場景
我想下載資源。我不希望資源被更多地下載一次。如果線程a下載資源1
它應該被緩存,並且線程b應該等待並使用緩存資源1
如果它嘗試同時下載資源1
。如果線程c想要下載資源2
,則不應該受線程a和b的影響。有條件的線程鎖定
嘗試
我試圖實現下面的場景:
using System;
using System.Collections.Generic;
using System.Threading;
namespace ConsoleApplication1
{
class ConditionalThreadLockingProgram
{
private static readonly object _lockObject = new object();
private static readonly Dictionary<int, string> Locks =
new Dictionary<int, string>();
private static readonly Dictionary<int, string> Resources =
new Dictionary<int, string>();
public static string GetLock(int resourceId)
{
lock (_lockObject)
{
if (Locks.ContainsKey(resourceId))
{
return Locks[resourceId];
}
return Locks[resourceId] = string.Format(
"Lock #{0}",
resourceId
);
}
}
public static void FetchResource(object resourceIdObject)
{
var resourceId = (int)resourceIdObject;
var currentLock = GetLock(resourceId);
lock (currentLock)
{
if (Resources.ContainsKey(resourceId))
{
Console.WriteLine(
"Thread {0} got cached: {1}",
Thread.CurrentThread.Name,
Resources[resourceId]
);
return;
}
Thread.Sleep(2000);
Console.WriteLine(
"Thread {0} downloaded: {1}",
Thread.CurrentThread.Name,
Resources[resourceId] = string.Format(
"Resource #{0}",
resourceId
)
);
}
}
static void Main(string[] args)
{
new Thread(FetchResource) { Name = "a" }.Start(1);
new Thread(FetchResource) { Name = "b" }.Start(1);
new Thread(FetchResource) { Name = "c" }.Start(2);
Console.ReadLine();
}
}
}
問題
是否行得通?任何問題?
你試過了嗎? – PinnyM 2013-02-18 23:21:58
是的,我認爲它有效。但我對多線程很陌生。 – knut 2013-02-18 23:23:21
我可能會建議使用字典的SyncRoot,而不是創建自己的鎖。 GetLock將使用(((IDictionary)Locks).SyncRoot)和FetchResouce將使用(((IDictionary)Resources).SyncRoot) – 2013-02-18 23:33:27