假设:
在这种情况下,您需要挥发性或原子参考或类似的东西吗?
该条指出:
如果您严格遵守单一写入器原则,则不需要内存障碍。
这似乎表明,在我描述的情况下,你真的不需要做任何特殊的事情。
我做了一个测试,结果很奇怪:
import org.junit.Test;
public class ThreadTest {
int onlyWrittenByMain = 0;
int onlyWrittenByThread = 0;
@Test
public void testThread() throws InterruptedException {
Thread newThread = new Thread(new Runnable() {
@Override
public void run() {
do {
onlyWrittenByThread++;
} while (onlyWrittenByMain < 10 || onlyWrittenByThread < 10);
System.out.println("thread done");
}
});
newThread.start();
do {
onlyWrittenByMain++;
// Thread.yield();
// System.out.println("test");
// new Random().nextInt();
} while (onlyWrittenByThread < 10);
System.out.println("main done");
}
}
有时运行this会输出“线程完成”,然后永远挂起。有时它确实完成了。所以线程可以看到主线程所做的更改,但显然main并不总是看到线程所做的更改?
如果我把系统或线程放进去。屈服,或随机调用,或使onlywritenbythread易失性,它每次都会完成(尝试了大约10次)。
这是否意味着我上面提到的博客文章是不正确的?即使在单个作者的情况下,你也必须有记忆障碍?
没有人能完全回答这个问题,所以我想我猜这可能是正确的,不需要内存屏障,但如果没有创建“先发生后发生”关系的东西,java编译器和hotspot可以进行优化(例如提升),这将使它不能做自己想要的事情。
这是必需的,因为读线程可能看不到读字段上的更改。你应该建立一种先发生后发生的关系。
代码中的主要问题不是CPU将做什么,而是JVM将如何处理它:变量提升的风险很高。这意味着JMM(Java内存模型)允许JVM重写:
public void run() {
do {
onlyWrittenByThread++;
} while (onlyWrittenByMain < 10 || onlyWrittenByThread < 10);
System.out.println("thread done");
}
作为另一段代码(注意局部变量):
public void run() {
int localA = onlyWrittenByMain;
int localB = onlyWrittenByThread;
do {
localB ++;
} while (localA < 10 || localB < 10);
System.out.println("thread done");
}
碰巧这是hotpost进行的一个相当常见的优化。在您的情况下,一旦进行了优化(可能不是在您调用该方法时立即进行,而是在几毫秒后),您在其他线程中所做的任何事情都将永远不会从该线程中可见。
问题是在多核系统上缓存——如果没有像易失性这样的强制先发生关系(内存障碍之类的东西),您可以让您的写入线程写入其内核缓存中变量的副本,而您的所有读取线程读取另一个内核上变量的另一个副本。另一个问题是原子性,另一个答案解决了这个问题。
假设我有一组从客户机发送到服务器的请求ID。服务器的响应返回我发送的请求ID,然后我可以将其从哈希集中删除。这将以多线程的方式运行,因此多个线程可以在哈希集中添加和删除ID。然而,由于生成的ID是唯一的(从线程安全的源代码,比如现在的,它会针对每个新请求进行更新),是否需要是? 我认为这可能导致问题的唯一情况是遇到冲突,这可能需要对底层对象进行数据结构更改,但在这个用例中似乎不会发生这种情况。
问题内容: 说我有一个全局对象: 有一个线程定期运行以从远程获取新编号并更新(仅写入): 并且有一个或多个线程随机使用此全局变量(仅读取): 您可以看到我不使用任何锁或对其进行保护,对吗?是否有可能引起问题的潜在问题? 更新: 就我而言,读取线程必须实时获取最新的值并不是很重要。我的意思是,如果有任何问题(由于缺少锁定/同步而导致)使一个读取线程错过了该值,那就没关系了,因为它将有机会尽快运行相同
考虑以下代码: 在一次采访中,我被问到了以下问题:如果只有一个线程调用,而多个线程可以调用,那么这个代码是线程安全的吗? 我知道,如果我们有多个写入线程,竞争条件可能会发生。然而,当每个读取线程中只有一个写入线程时,我们将按顺序获取值,即我们不会在之后读取,因为的写入发生在第一次读取,因此,在同一线程中的所有后续读取。这个推理是正确的,还是我漏掉了什么?
我有一张地图。假设: 多个线程正在访问此映射,但是每个线程只能访问映射中自己的条目。这意味着,如果线程T1将对象A插入到映射中,则保证没有其他线程将访问对象A。最后,线程T1也将删除对象A。 还可以保证没有线程会遍历映射。 这张地图需要同步吗?如果是,您将如何同步?(ConcurrentHashMap、Collections.synchronizedMap()或synchronized block
我在datasource password字段中有特殊字符,如“(双引号)、@,~,!,%,&,},”。当我运行springboot应用程序时,当它试图连接到我遇到的数据库时- 我的问题是: (1)是否有方法查看Spring尝试连接时使用的密码? (2)是否需要转义中密码中的任何特殊字符? 我能够使用一个独立的java程序连接到数据库,但是我必须转义密码中的双引号。我在后端使用了SpringBoo
类AnagramGameDefault模拟一个字谜游戏。 submitScore()应该重新计算位置,得分最高的位置为1,同一位置上可以有多个球员。 tester类: