gpt4 book ai didi

java - 使用时间戳更新的线程安全集?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:50:45 25 4
gpt4 key购买 nike

我有一个包含数千个电话号码的集合。当我的服务收到新帐户请求时,它会根据列表检查电话号码,以确保它不是已知的垃圾邮件号码。如果电话号码列表超过一周,该方法会从外部服务器获取列表的最新副本并将其读入内存。然后它更新“timestamp”变量以反射(reflect)列表的最后更新时间。像这样的东西:

public class SpamPhoneNumberManager() {

private Set<String> spamPhoneNumbers;
private long timestamp;

public SpamPhoneNumberManager() {
updateSpamPhoneNumbers();
}

public Set<String> getSpamPhoneNumbers() {
if(timestamp - System.currentTimeMillis() > ONE_WEEK) {
updateSpamPhoneNumbers();
}
return spamPhoneNumbers;
}

private void updateSpamPhoneNumbers() {
Set<String> newSpamPhoneNumbers = new HashSet<>();
//populate set from file on server
spamPhoneNumbers = Collections.unmodifiableSet(newSpamPhoneNumbers);
timestamp = System.currentTimeMillis();
}

}

多个线程可以并发调用get()方法。在当前的实现中,我想不出任何并发问题。在我能想到的最坏情况下,列表由多个线程连续更新。是否需要使此线程安全?如果是这样,最好的方法是什么?

最佳答案

Is there a need to make this threadsafe?

您当前的类不是线程安全的,因为多个线程可以调用 getSpamPhoneNumbers() 并检查 if 条件,这不是原子的。因此,多个线程尝试调用 updateSpamPhoneNumbers 导致竞争条件,因此会有中间状态,其中 spamPhoneNumbers 获得一个值和 timestamp不同的值(如果任何其他线程调用 get 方法发现并返回这些不一致的值,如下所述)。

简而言之,会出现如下情况:

Thread1 -> 使用 spamPhoneNumbersThread1 更新 spamPhoneNumbers 并设置 timestampThread1

Thread2 -> 更新 spamPhoneNumbersThread2(假设 timestamp 仍未更新)

Thread3 -> 调用 getSpamPhoneNumbers() 并且不进入 if block 并返回 spamPhoneNumbersThread2(针对 timestampThread1 进行验证)

这里的重点是明显存在竞争条件,您会看到不一致的(来自不同线程的)timestampspamPhoneNumbers 值。

If so, what's the best way to do this?

解决方案是您需要在 spamPhoneNumbers 对象上进行同步,以便一次只能有一个线程访问它。

public Set<String> getSpamPhoneNumbers() {
synchronized(spamPhoneNumbers) {
if(timestamp - System.currentTimeMillis() > ONE_WEEK) {
updateSpamPhoneNumbers();
}
}
return spamPhoneNumbers;
}

private void updateSpamPhoneNumbers() {
Set<String> newSpamPhoneNumbers = new HashSet<>();
//populate set from file on server
spamPhoneNumbers = Collections.unmodifiableSet(newSpamPhoneNumbers);
timestamp = System.currentTimeMillis();
}

附注:您不需要在 updateSpamPhoneNumbers() 中进行任何同步,因为它是 private,但如果您以后改变主意并且这个方法变成了public,你必须在这里也需要同步。

关于java - 使用时间戳更新的线程安全集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43299926/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com