今天我实验室的敏感操作完全错了.电子显微镜上的执行器越过它的边界,在一系列事件之后,我损失了1200万美元的设备.我已将故障模块中的40K以上线路缩小到:
import java.util.*;
class A {
static Point currentPos = new Point(1,2);
static class Point {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) {
new Thread() {
void f(Point p) {
synchronized(this) {}
if (p.x+1 != p.y) {
System.out.println(p.x+" "+p.y);
System.exit(1);
}
}
@Override
public void run() {
while (currentPos == null);
while (true)
f(currentPos);
}
}.start();
while (true)
currentPos = new Point(currentPos.x+1, currentPos.y+1);
} …Run Code Online (Sandbox Code Playgroud) 我正在阅读B. Goetz Java Concurrency在实践中,现在我正处于section 3.5安全的出版物中.他说:
// Unsafe publication
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
Run Code Online (Sandbox Code Playgroud)
这种不正确的发布可能允许另一个线程观察部分构造的对象.
我不明白为什么可以观察到部分构造的子对象.假设构造函数Holder(int)不允许this转义.因此,构造的引用只能由调用者观察到.现在,正如JLS 17.7所述:
无论是否将它们实现为32位或64位值,对引用的写入和读取始终是原子的.
线程不可能观察到部分构造的对象.
我哪里错了?
在玩一些jcstress代码时,我注意到两个对我来说很新的参数:StressLCM和StressGCM。
对我来说,要做的第一件事就是在源代码本身中搜索这些内容,尽管我发现了一些内容,但仍不清楚它们的实际作用。我真的很希望在源代码中看到一些注释,但这些注释可能会有所帮助,但是没有运气。
我还发现了在其中添加了这些错误的错误描述,但该解释对我而言毫无意义:
在LCM / GCM中随机化指令调度。
有人可以用简单的英语解释他们的工作吗?
出于教育目的,我正在编写一个简单的版本AtomicLong,其内部变量受到保护ReentrantReadWriteLock.这是一个简化的例子:
public class PlainSimpleAtomicLong {
private long value;
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public PlainSimpleAtomicLong(long initialValue) {
this.value = initialValue;
}
public long get() {
long result;
rwLock.readLock().lock();
result = value;
rwLock.readLock().unlock();
return result;
}
// incrementAndGet, decrementAndGet, etc. are guarded by rwLock.writeLock()
}
Run Code Online (Sandbox Code Playgroud)
我的问题:由于"value"是非易失性的,其他线程是否有可能通过不正确的初始值来观察PlainSimpleAtomicLong.get()?例如,线程T1创建L = new PlainSimpleAtomicLong(42)并与线程共享引用T2.为T2保证遵守L.get()为42?
如果没有,包装this.value = initialValue;到写锁定/解锁会有所作为吗?
java命令的帮助菜单说该-server选项是选择"服务器"VM.它还声明'server'是默认选项.为什么这么多余?
编辑:
如果有任何帮助,"java -version"会产生:
java version "1.8.0_191"
Java(TM) SE Runtime Environment (buil 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
Run Code Online (Sandbox Code Playgroud) 让我们看看这个简单的Java程序:
import java.util.*;
class A {
static B b;
static class B {
int x;
B(int x) {
this.x = x;
}
}
public static void main(String[] args) {
new Thread() {
void f(B q) {
int x = q.x;
if (x != 1) {
System.out.println(x);
System.exit(1);
}
}
@Override
public void run() {
while (b == null);
while (true) f(b);
}
}.start();
for (int x = 0;;x++)
b = new B(Math.max(x%2,1));
}
}
Run Code Online (Sandbox Code Playgroud)
主线程
主线程创建的实例B与x设置为1,则该实例写入静态字段 …
当我向JMM提出与“最终”相关的担保时,我最近感到困惑。这是JMM的摘录和示例
图4给出了一个示例,该示例演示了最终场与正常场的比较。类FinalFieldExample有一个最终整数字段x和一个非最终整数y。一个线程可以执行方法writer(),而另一个线程可以执行方法reader()。因为writer()在对象的构造函数完成之后写入f,所以将保证reader()可以看到fx的正确初始化值:它将读取值3。因此,不能保证reader()方法的值是4
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的困惑是,对象'Obj'具有final和non-final字段是否已完全初始化并由线程'T'引用,T将仅看到final字段的正确值吗?构造后不会发生突变的非最终字段呢?我了解,如果在构造线程“ T”之后对其进行了突变,则可能看不到新值(除非该字段为volatile)。但是,如果该领域是非最终性和非易失性的,并且在构造之后没有发生变化,我该怎么办?
JVM如何实现与“最终”相关联的保证?例如,对于易失性,存在存储障碍。