Tag: 发生在之前

在thread.start之前发生的所有事情都可以生成调用start的线程吗?

现在已经有很好的答案已经在stackoverflow上,但他们没有给我我想要的明确答案。 假设你有一个方法 Dosomething(); doAnother(); int x = 5; Runnable r = new Runnable(){ public void run(){ int y = x; x = 7; System.out.println(z);} } new Thread(r).start() 现在同时这个方法正在运行,在调用thread.start之前,一些全局非易失性变量z从4变为5。 由于z发生在thread.start之前,程序是否会保证打印5? 另外,如果我们以这种方式讨论它,那么可以肯定地说thread.start()永远不会被重新排序。 根据被调用的那个线程的意义开始,就好像到那一点的一切都是顺序的。 比如说我们有 int k = 8; new Thread(() -> {}).start() 现在……在该线程的视角中,无论是首先调用start还是分配k,都不会产生影响。所以这可以重新排序,但是因为在保证之前发生了,这是不可能的? java规范没有说明这一点的强烈声明。 相反它说 当一个语句调用Thread.start()时,每个语句都与该语句有一个before-before关系 然而,k = 8并不是在与该陈述的关系之前发生的…… 我甚至不确定他们的意思是在与start方法的关系之前发生了什么事情,除非您使用相同的监视器锁定 synchronized(this){ int k = 8;} synchronized(this) { […]

没有内存屏障的无序写入:数据竞争的唯一可能原因?

在Brian Goetz的实践中通过Java Concurrency时,我遇到了以下行: 当一个变量被多个线程读取并由至少一个线程写入时,会发生数据争用,但读取和写入不是由before-before排序的 。 正确同步的程序是没有数据竞争的程序; 正确同步的程序表现出顺序一致性,这意味着程序中的所有操作似乎都以固定的全局顺序发生。 我的问题是,乱序是写java或其他编程语言中数据竞争条件的唯一原因吗? UPDATE 好的,我做了一些关于数据竞争的调查,并从oracle官方网站上找到了以下内容: 线程分析器检测在执行multithreading进程期间发生的数据争用。 数据竞争发生在: 单个进程中的两个或多个线程同时访问同一个内存位置,并且 至少有一个访问是用于写入,和 线程没有使用任何独占锁来控制它们对该内存的访问。 当这三个条件成立时, 访问顺序是非确定性的 ,并且计算可以根据该顺序从运行到运行给出不同的结果。 某些数据争用可能是良性的(例如,当内存访问用于忙等待时),但许多数据争用是程序中的错误。 在这一部分中,提到: 访问顺序是非确定性的 它是在讨论线程访问内存位置的顺序吗? 如果是,那么同步永远不会保证线程将访问代码块的顺序。 那么,同步如何解决数据竞争问题呢?

Java发生在之前和同步

我对Java的发生和同步有一些分歧。 想象一下以下场景: 主线程 MyObject o = new MyObject(); // (0) synchronized (sharedMonitor) { // (1) add the object to a shared collection } // (2) spawn other threads 其他主题 MyObject o; synchronized (sharedMonitor) { // (3) retrieve the previously added object } // (4) actions to modify the object 请注意, MyObject的实例变量既不是volatile ,也不是final 。 MyObject的方法不使用同步。 我的理解是: […]

不稳定的出版物保证多深?

众所周知,如果我们有一些对象引用并且此引用具有final字段 – 我们将看到来自final字段的所有可到达字段(至少在构造函数完成时) 例1: class Foo{ private final Map map; Foo(){ map = new HashMap(); map.put(1,”object”); } public void bar(){ System.out.println(map.get(1)); } } 正如我在这种情况下所做的那样,我们保证bar()方法始终输出object因为: 我列出了Foo类的完整代码,地图是最终的; 2.如果某个线程会看到Foo引用和这个引用!= null,那么我们保证从最终的map引用值可以到达的是实际的 。 我也是这么认为的 例2: class Foo { private final Map map; private Map nonFinalMap; Foo() { nonFinalMap = new HashMap(); nonFinalMap.put(2, “ololo”); map = new HashMap(); map.put(1, “object”); } […]