克隆是O(n),但這並不能說明整個故事。克隆可以是淺層克隆(只需複製表中的引用)或深層克隆(複製對象本身)。深度克隆可能是一項非常昂貴的操作。搜索時間也可能不同,從僅檢查單個整數字段的快速搜索到比較多個值並且非常昂貴的複雜搜索。另外,如果您的數據在您正在搜索的字段上排序,則搜索爲O(log n),這將比O(n)快得多。
如果您需要考慮某人將添加,修改或刪除行的可能性,那麼您必須鎖定或克隆。如果您只進行一次搜索,那麼克隆並不合理,因爲您必須鎖定表以克隆它。除非您的搜索異常昂貴,否則克隆最有可能需要比搜索更長的時間。
你說修改很少,而且搜索頻繁。在這種情況下,我建議您使用讀寫器鎖,它將支持無限數量的讀者或一位作者。在.NET中,您可能需要ReaderWriterLockSlim。使用它,您的代碼如下所示:
private ReaderWriterLockSlim tableLock = new ReaderWriterLockSlim();
public bool Search(string s)
{
tableLock.EnterReadLock();
try
{
// do the search here
return result;
}
finally
{
tableLock.ExitReadLock();
}
}
任何數量的讀取器都可以同時搜索表。當然,他們不會修改它。如果要修改表,你必須獲取寫入鎖定:
public void Modify(string s)
{
tableLock.EnterWriteLock();
try
{
// do the modification here
return;
}
finally
{
tableLock.ExitWriteLock();
}
}
當一個線程試圖進入寫入鎖,它必須等待所有現有讀者退出。在請求寫入鎖定之後進入的讀者必須等待現有的讀取器退出,並且讓作者獲取然後釋放鎖定。
在您描述的情況類似的情況下,讀寫器鎖對我來說效果非常好:頻繁讀取和不頻繁寫入。如果沒有其他,因爲它很容易測試,所以值得研究。
如果搜索和更新大致相等,讀寫器鎖仍然可以正常工作,因爲它仍然允許多個閱讀器。想一想,如果寫得更加頻繁,它甚至會運行良好,同樣因爲它會在可能的情況下允許多次讀取。當我有一個可以搜索和更新的數據結構時,我幾乎總是使用ReaderWriterLockSlim
。
還有其他的解決方案,但它們涉及的定製數據結構可能更難實施和維護。我建議你試一試讀者/寫者鎖定。如果在此之後,分析表明線程仍在等待鎖定並減慢應用程序的響應時間,則可以查看備選方案。
不過,我有點擔心,你所做的不僅僅是搜索。你的樣本選擇了一堆行,然後你做if (t.Any()) { ... }
。你在做什麼{ ... }
?如果這需要很長時間,則最好將代碼克隆爲您選擇的行。然後,您可以將結果集上的鎖和派對釋放到您的內容中,而不會影響其他需要訪問數據結構的線程。
我在這裏沒有看到真正的問題!我認爲你應該嘗試這樣做,它不會給你 –
的想法,爲了嘗試這一點,我必須花費很多精力(應用程序是巨大的),並且只有在某些改進很可能時我纔會嘗試 –
你有任何理由'鎖定「時搜索?我可以理解,正如你所說的一些函數可能會改變這些值。我認爲鎖定只有在你修改時才需要。 –