[英]How to create single dimensional, two dimensional,three dimensional as well as multi dimensional array using C#?
[英]c# How to create a thread safe, two dimensional lock collection?
我正在嘗試實現線程安全的二維集合,以控制對多個資源的訪問。 從我看到的問題出發,我需要在集合級別(這很簡單)和單個對象級別上執行鎖定,但不一定要同時執行鎖定,這可能會引起一些問題。
public class LockStore
{
private object _syncLock = new object();
private Dictionary<string, StoredLock> _locks = new Dictionary<string, StoredLock>();
public StoredLock GetOrAdd(string id, StoredLock lockDetails)
{
if (!_locks.ContainsKey(id))
lock (_syncLock)
{
if (!_locks.ContainsKey(id))
_locks.Add(id, lockDetails);
}
return _locks[id];
}
public void Remove(string id)
{
lock (_syncLock)
{
_locks.Remove(id);
}
}
}
public class StoredLock
{
public string Id { get; set; }
public DateTime CreatedDateTime { get; set; }
}
例如,一個線程可以調用LockStore.GetOrAdd()方法,並返回一個StoredLock對象。 然后,我想鎖定StoreLock對象,以防止其他線程能夠訪問它,但又不持有整個字典的鎖。
var id = "someId"
var storedLock = lockStore.GetOrAdd(id, new StoredLock());
lock (storedLock)
{
//Do something
}
在某個時候完全處於不同的線程中...
lockStore.Remove(id);
在獲取存儲在LockStore內的StoredLock對象上的鎖時,該鎖沒有為LockStore持有,因此理論上可以為該特定ID調用LockStore.Remove(),因為Remove()方法不了解鎖保留在它實際包含的對象上。 我不確定在這種情況下會發生什么,但我認為這不會好!
另外,我認為這可能會違反以下設計原則:用於鎖定的對象不能公開訪問?
我對此實在感到茫然,因此任何建議:解決問題或實際方法將不勝感激。
編輯:要特別具體-我不想同時持有LockStore集合和單個StoredLock上的鎖,因為這將大大減慢處理速度。
了解問題之后,我認為您應該執行以下操作:
public class LockStore
{
private readonly Dictionary<string, StoredLock> m_Dictionary =
new Dictionary<string, StoredLock>();
public void UseResource(string resource_id, Action<StoredLock> action)
{
StoredLock stored_lock = null;
lock(m_Dictionary)
{
if (m_Dictionary.ContainsKey(resource_id))
{
stored_lock = m_Dictionary[resource_id];
}
else
{
stored_lock = new StoredLock
{
Id = resource_id,
CreatedDateTime = DateTime.Now
};
m_Dictionary.Add(resource_id,stored_lock);
}
}
lock(stored_lock)
{
action(stored_lock);
}
}
public bool RemoveLock(string resource_id)
{
lock (m_Dictionary)
{
if (!m_Dictionary.ContainsKey(resource_id))
return true;
var stored_lock = m_Dictionary[resource_id];
bool taken = false;
Monitor.TryEnter(stored_lock, ref taken);
if (!taken)
return false;
try
{
m_Dictionary.Remove(resource_id);
}
finally
{
Monitor.Exit(stored_lock);
}
return true;
}
}
}
該代碼的設計不是很完美,但是可以正常工作。 您應該努力使它變得更好。
基本上,此類允許您從線程1執行類似的操作:
lockStore.UseResource("resource1", sl =>
{
//Do some processing with s1
});
並在線程2中執行以下操作:
var removed = lockStore.RemoveLock("resource1");
如果某個線程仍對該對象保持鎖,則RemoveLock
將立即返回並為您提供false
的返回值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.