我试图简单地测试JLS保证的最终字段的初始化安全性.这是我写的一篇论文.但是,根据我当前的代码,我无法让它"失败".有人可以告诉我我做错了什么,或者这只是我必须反复运行然后看到一个不幸的时机失败?
这是我的代码:
public class TestClass {
    final int x;
    int y;
    static TestClass f;
    public TestClass() {
        x = 3;
        y = 4;
    }
    static void writer() {
        TestClass.f = new TestClass();
    }
    static void reader() {
        if (TestClass.f != null) {
            int i = TestClass.f.x; // guaranteed to see 3
            int j = TestClass.f.y; // could see 0
            System.out.println("i = " + i);
            System.out.println("j = " + j);
        }
    }
}
我的线程正在调用它:
public class TestClient {
    public static void …在Java的内存模型保证了之前发生的对象的构造和释放的关系:
从对象的构造函数的末尾到该对象的终结器(第12.6节)的开始有一个发生前的边缘.
以及最终字段的构造函数和初始化:
当构造函数完成时,对象被认为是完全初始化的.在该对象完全初始化之后只能看到对象引用的线程可以保证看到该对象的最终字段的正确初始化值.
还有一个关于volatile字段的保证,因为关于对这些字段的所有访问的关系都存在:
写入易失性字段(第8.3.1.4节) - 在每次后续读取该字段之前发生.
但是常规的,古老的非易失性领域呢?我已经看到很多多线程代码在使用非易失性字段构造对象后不会创建任何类型的内存屏障.但是我从来没有见过或听说过任何问题,而且我自己也无法重建这种局部结构.
现代JVM在施工后是否只是放置了内存屏障?避免在施工周围重新排序?还是我很幸运?如果是后者,是否可以编写可以随意重现部分构造的代码?
编辑:
澄清一下,我说的是以下情况.假设我们有一个班级:
public class Foo{
    public int bar = 0;
    public Foo(){
        this.bar = 5;
    }
    ...
}
一些Thread T1实例化一个新Foo实例:
Foo myFoo = new Foo();
然后将实例传递给其他线程,我们将调用它T2:
Thread t = new Thread(() -> {
     if (myFoo.bar == 5){
         ....
     }
});
t.start();
T1 进行了两次我们感兴趣的写作:
bar了新实例化的值5myFoomyFoo变量对于T1,我们得到写#1 发生的保证- 在写#2 之前:
线程中的每个动作都发生 …
让我们看看这个简单的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));
    }
}
主线程
主线程创建的实例B与x设置为1,则该实例写入静态字段 …
这是我试图解决的问题,但不知道该怎么做:我有一个对象数组(比如大小为100),每个对象都有一些id.
Class Employee{
   int EmployeeId;
}
有10个线程将从该数组中读取数据并将其插入数据库.
如何确保数据按照递增顺序的EmployeeId顺序插入到DB中. 例如:
如果array具有EmployeeID 6,8和4的对象,那么这些对象应按照EmployeeID 4,6和DB中的8顺序插入到DB中.如何为此编写多线程代码?
更新:请忽略数据库部分,如果它令人困惑,我的主要目的是同时处理,但按顺序处理.
public class suspendCheck extends Thread{
    int t ;
    public static void main(String args[]) throws InterruptedException {
        suspendCheck as = new suspendCheck();
        Thread t2 = new Thread(as);
        t2.start();
        Thread t3 = new Thread(as);
        t3.start(); }
    public void run(){
        if(t==0){
        System.out.println("JAVA Develper");
        t= ++t;
        }
        else{
            System.out.println("JAVA Test");
            }
        }
}
多次运行此程序后,存在差异和差异:
通常:
JAVA Develper
JAVA Develper
并偶尔:
JAVA Develper
JAVA Test
我对此感到震惊.我哪里做错了?