我不确定这是否是绝对最好的地方,但我认为答案的概率最高(因为主题).
有没有人遇到过Java语言规范的mobi(亚马逊Kindle)版本?我知道我可以在Kindle上阅读PDF文件,但与mobi相比,它的体验更少.
当且仅当所有顺序一致的执行没有数据争用时,程序才能正确同步.
根据讨论,如果一个正确同步的程序仍允许数据竞争吗?(第一部分),我们得出以下结论:
程序可以正确同步并具有数据竞争.
两个结论的结合意味着它必须存在这样一个例子:
程序的所有顺序一致的执行都是数据竞争的,但是这样的程序的正常执行(除了顺序一致的执行之外的执行)包含数据竞争.
经过深思熟虑,我还是找不到这样的代码样本.那你呢?
根据Java语言规范(例17.4-1),以下片段(从开始A == B == 0)...
Thread 1 Thread 2
-------- --------
r2 = A; r1 = B;
B = 1; A = 2;
Run Code Online (Sandbox Code Playgroud)
......可以导致r2 == 2和r1 == 1.这是因为执行的结果B = 1;不依赖于是否r2 = A已经执行,因此JVM可以自由地交换这两个指令的执行顺序.换句话说,规范允许以下交错:
Thread 1 Thread 2
-------- --------
B = 1;
r1 = B;
A = 2;
r2 = A;
Run Code Online (Sandbox Code Playgroud)
这显然导致r2 == 1和r1 == 1.
假设我们稍微调整一下这个例子:
Thread 1 Thread 2
-------- --------
r2 …Run Code Online (Sandbox Code Playgroud) JLS第17.5.3段(最终字段的后续修改)经常使用术语最终字段安全上下文.虽然,从规范中可以理解(如果我在这里错了,请纠正我)
An implementation may provide a way to execute a block of code
in a final-fieldsafe context.
Run Code Online (Sandbox Code Playgroud)
确切的行为取决于实现,仍然没有明确的术语定义.
我可以假设,如果我们有一个最终字段冻结F(一个发生在对象构造的末尾或通过反射API设置的最终字段)和一个动作A,那么发生在之前(F,A ),那么A是在最终现场安全的背景下?
以下代码用于Integer使用对象实习:
Integer.valueOf("1")
Run Code Online (Sandbox Code Playgroud)
从API文档中不清楚此代码是否Boolean也使用了interned对象:
Boolean.valueOf("true")
Run Code Online (Sandbox Code Playgroud)
显然,它可能.但是它必须吗?
UPDATE
我同意源代码可以解释实际发生的事情(BTW,感谢答案).为了使问题变得不那么简单,Java API规范或JSL的任何部分是否告诉必须发生什么?
对这样的代码提出问题是很自然的:
String str = "true";
if (Boolean.valueOf(str) == Boolean.TRUE) { ... }
Run Code Online (Sandbox Code Playgroud)
结果取决于"对象实习"是否得到保证.最好完全避免使用这些代码true而不是Boolean.TRUE(而不是查找任何规范或来源中的详细信息),但这是提出问题的正当理由.
注意:事实上,我没有看到Integer任何Google搜索规范中对象实习的保证.所以,它可能只是一个没人应该依赖的实现细节.
I'm reading Chapter 17. Threads and Locks of JLS and the following statement about sequential consistency in Java seems incorrect to me:
If a program has no data races, then all executions of the program will appear to be sequentially consistent.
They define a data race as:
When a program contains two conflicting accesses (§17.4.1) that are not ordered by a happens-before relationship, it is said to contain a data race.
They define conflicted accesses as:
Two accesses to (reads …
代码示例:
class Obj1 {
int f1 = 0;
}
volatile Obj1 v1;
Obj1 v2;
Thread 1 | Thread 2 | Thread 3
-------------------------------------------------
var o = new Obj1(); | |
o.f1 = 1; | |
v1 = o; | |
| v2 = v1; |
| | var r1 = v2.f1;
Is (r1 == 0) possible?
Run Code Online (Sandbox Code Playgroud)
这里的对象o:
Thread 1到Thread 2通过volatile字段v1Thread 2到Thread 3 …内存模型在 17.4 中定义。内存模型。
17.5 中给出了现场final多线程保证。最终字段语义。
我不明白为什么这些是单独的部分。
AFAIKfinal和内存模型都提供了一些保证。
任何真正的程序执行都必须遵守这两个保证。
但现在很清楚这些final保证是否适用于用于验证 17.4.8 中因果关系要求的中间执行。执行和因果关系要求。
另一个不清楚的时刻是17.5.1。Final Fields 的语义定义了一个新的“special” ,它与内存模型happens-before中的不同:happens-before
此happens-before排序不会与其他happens-before排序传递地关闭。
如果它们相同happens-before,则happens-before不再是偏序(因为它不具有传递性)。
我不明白这怎么不会破坏事情。
如果这些不同happens-before,那么就不清楚 17.5 中的是什么。Final Field Semantics确实如此。17.4中
的。内存模型用于限制读取可以返回的内容:happens-before
非正式地,如果没有happens-before排序来阻止
r读取,则允许读取查看写入的结果。w
但是17.5。最后的字段语义是一个不同的部分。
考虑以下简化的测试用例:
import java.util.AbstractList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
public final class Example {
static class PairList<A, B> {
public void replaceAllSecond(Function<? super B, ? extends B> secondFunction) {}
public void replaceAllSecond(BiFunction<? super A, ? super B, ? extends B> secondFunction) {}
}
static class ImmutableList<E> extends AbstractList<E> {
public static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) {return null;}
public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) {return null;}
public static <E> ImmutableList<E> copyOf(Iterator<? extends E> …Run Code Online (Sandbox Code Playgroud) 我有以下课程:
public abstract Foo {
Foo() {}
public abstract Foo doSomething();
public static Foo create() {
return new SomePrivateSubclassOfFoo();
}
}
Run Code Online (Sandbox Code Playgroud)
我想将其更改为以下定义:
public abstract Foo<T extends Foo<T>> {
Foo() {}
public abstract T doSomething();
public static Foo<?> create() {
return new SomePrivateSubclassOfFoo();
}
}
Run Code Online (Sandbox Code Playgroud)
此更改二进制兼容吗?即,针对旧版本的类编译的代码是否可以使用新版本而无需重新复制?
我知道我需要改变SomePrivateSubclassOfFoo,这没关系.我也知道,当编译旧客户端代码时,此更改将触发有关原始类型的警告,这对我也是可以的.我只是想确保不需要重新编译旧的客户端代码.
从我的理解,这应该是好的,因为擦除T是Foo,这样的签名doSomething在字节码是和以前一样.如果我看一下印刷的内部类型签名javap -s,我确实看到了这个确认(虽然打印的"非内部"类型签名没有-s做不同).我也测试了这个,它对我有用.
但是,Java API Compliance Checker告诉我这两个版本不是二进制兼容的.
什么是正确的?JLS是否保证二进制兼容性,或者我在测试中是否幸运?(为什么会发生这种情况?)