有没有使用锁保持数据一致性的方法?

时间:2013-11-06 15:00:59

标签: multithreading caching concurrency race-condition lockless

我正在尝试为从外部数据源获取的数据实现缓存。我试图弄清楚我是否可以避免锁定并使用时间戳来确保过时的数据永远不会插入缓存中。是否已经为此开发了一种机制?让我举个例子:

    // Reader thread does
   1 Data readData(id) {
   2       Data data = cache.get(id);
   3       if(data == null)
   4           data = extDataSrc.readData(id);
   5       cache.put(id, data);   
   6       return data;    }

    // Writer thread does
   7 void updateData(id, Data data) {
   8        extDataSrc.updateData(id, data);
   9        cache.remove(id); 
   10 }

所以现在没有锁定,当缓存中没有id时,读者可能会调用extDataSrc。如果同时编写器更新相同的id,则有可能在编写器提交之前,读取器读取过时数据并从extDataSrc调用返回延迟。同时,writer执行cache.remove(id)(缓存中没有数据,因此不会删除任何内容)并返回。 Reader然后执行cache.put(id)。 我认为可以通过使用时间戳来避免这种情况,这样当读取器检查缓存时,它会保存时间戳TR1(在第2行之后:检查缓存的id时)。 Writer在执行删除后保存TW1(在第9行:更新时间之后)。读取器执行第4行后,再次保存TR2(第4行:读取完成后,缓存更新即将开始)。这里,如果TR2> TW1,它跳过cache.put,因为其他线程在读取缓存后进行了更新。

因此,TR1 = 100,TW1 = 105,TR2 = 110 => skip cache.put。

有道理吗?

2 个答案:

答案 0 :(得分:1)

答案 1 :(得分:0)

我建议在执行extDataSrc.readData(id)时在缓存中放置一个临时同步对象。首先,如果2个读取器线程请求相同的项目,则第二个线程不需要发出冗余请求,而只是等待第一个发出的请求。其次,当作者看到请求正在进行时,它可以简单地将其数据放入缓存并提供读取器。当readData完成时,它必须检查写入器是否已满足请求(缓存项是数据,而不是临时对象),只需从extDataSrc中丢弃(陈旧)数据。 / p>

而不是使用时间戳,我会在数据对象中使用版本号 - 即使有几个进程写入同一个extDataSrc,它也会起作用。