Java 我是否需要使用volatile if update to other thread';缓存不是时间限制
我有一个带有一个方法的单例对象:Java 我是否需要使用volatile if update to other thread';缓存不是时间限制,java,multithreading,thread-safety,volatile,Java,Multithreading,Thread Safety,Volatile,我有一个带有一个方法的单例对象: class static single { String static somefileContent; public static void set(String str){somefileContent=str;} public static String get(){return somefileContent;} } 我有两条线 一个线程从操作中的single.get()查询内容,大约100次/秒 另一个线程监视某个文件以在期间内使用s
class static single
{
String static somefileContent;
public static void set(String str){somefileContent=str;}
public static String get(){return somefileContent;}
}
我有两条线
一个线程从操作中的single.get()查询内容,大约100次/秒
另一个线程监视某个文件以在期间内使用set()方法更新字符串,如果文件被修改,则刷新内容
少数操作使用旧字符串值是可以接受的
我的问题是:我是否需要volatile,因为它不是时间限制
如果发生最坏的情况,读取线程是否不会永远更新
我只是想知道使用纯Java会发生什么?是的,读取线程可能在值得到更新后读取旧值。但就像我说的,读几遍旧值是可以接受的。我想知道旧值是否永远留在CPU缓存中
多亏了Vaspar的回答。更好地使用,您不需要使用volatile变量。get
调用应为ReadLocked(共享),而set
调用应为WriteLocked(独占)。一旦所有线程都获得各自的读锁,这些更改就会在所有线程中更新
所有实现都必须保证内存
写回操作的同步效果(如
锁定接口)也保持关联的读锁。
也就是说,成功获取读取锁的线程将看到所有
上次发布写锁时所做的更新
示例代码:
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
public class Single {
private static String somefileContent = null;
private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static final ReadLock readLock = readWriteLock.readLock();
private static final WriteLock writeLock = readWriteLock.writeLock();
public static String get() {
try {
readLock.lock();
return somefileContent;
} finally {
readLock.unlock();
}
}
public static void set(String str) {
try {
writeLock.lock();
somefileContent = str;
} finally {
writeLock.unlock();
}
}
}
你为什么不跑几次自己看看呢为什么不同步get/setmethods@alfasin“运行几次”是计算并发边缘情况的糟糕建议。@Chryly是真的,但在这种情况下,他将获得一致的行为(提示:他所谓的“最坏情况”)@alfasin他可能在本地x86上获得一致的行为,但如果他尝试将其移植到ARM,任何事情都可能发生变化。这就是为什么这是一个糟糕的想法。读写锁是允许的解决方案。我只是想知道使用纯Java是否可以接受?是的,读取线程可能在值得到更新后读取旧值。但正如我所说,很少时间阅读旧价值观是可以接受的。我想知道旧值是否会永远留在CPU缓存中。不客气。这种锁的设计是为了频繁阅读而不是频繁写作。此外,每次“读取”,在修改后,都保证看到更新。如果操作只是交换单个变量,那么Volatile变量或原子对象也可以用于此目的。如果您想执行一系列步骤,那么锁定是最好的方法。如果您想使用普通java,没有易失性/原子对象,那么读取旧值的线程将永远看不到新值,除非线程执行具有“之前发生”关系的
操作。例如:同步或类似的东西。只有这样,所有的变量才会刷新。如果线程没有这样的操作,它将永远看不到更新。-进一步阅读。在我提到的锁的例子中,它们是操作
满足关系发生之前的情况。因此,writer线程所做的更新在reader线程中可见。谢谢,before关系正是我问题的答案。