我正在用 Go 编写一个搜索引擎,其中我有一个单词倒排索引到每个单词的相应结果。有一组单词字典,因此单词已经转换为 a StemID
,它是一个从 0 开始的整数。这允许我使用一片指针(即 a sparse array
)将每个指针映射StemID
到包含结果的结构询问。例如var StemID_to_Index []*resultStruct
。如果aardvark
是,0
则指向 resultStruct 的指针aardvark
位于StemID_to_Index[0]
,nil
如果当前未加载该单词的结果,则该指针将位于。
服务器上没有足够的内存来将所有这些存储在内存中,因此每个结构StemID
将保存为单独的文件,并且可以将这些文件加载到StemID_to_Index
切片中。如果StemID_to_Index
当前nil
为此,StemID
则结果未缓存并需要加载,否则它已经加载(缓存),因此可以直接使用。每次加载新结果时,都会检查内存使用情况,如果超过阈值,则丢弃 2/3 的加载结果(这些 StemIDStemID_to_Index
设置nil
为 并强制进行垃圾收集。)
我的问题是并发。什么是最快和最有效的方法,我可以同时搜索多个线程,而不会出现不同线程尝试同时读取和写入同一位置的问题?我试图避免在所有内容上使用互斥锁,因为这会减慢每次访问尝试的速度。
您认为我会在工作线程中从磁盘加载结果,然后使用通道将指向该结构的指针传递给“更新程序”线程,然后nil
将StemID_to_Index
切片中的值更新为加载结果的指针吗?这意味着两个线程永远不会尝试同时写入,但是如果另一个线程尝试从StemID_to_Index
“更新程序”线程更新指针的确切索引中读取会发生什么?如果给一个线程一个nil
当前正在加载的结果的指针并不重要,因为它只会被加载两次,虽然这是一种资源浪费,但它仍然会提供相同的结果,因为这不太可能发生很多时候,这是可以原谅的。
此外,将要更新的指针发送到“更新程序”线程的工作线程如何知道“更新程序”线程何时完成更新切片中的指针?它应该只是休眠并继续检查,还是有一种简单的方法让更新程序将消息发送回推送到通道的特定线程?
慕丝7291255
相关分类