Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么可以';我不能证明我的代码中需要一个原子引用吗?_Java_Multithreading - Fatal编程技术网

Java 为什么可以';我不能证明我的代码中需要一个原子引用吗?

Java 为什么可以';我不能证明我的代码中需要一个原子引用吗?,java,multithreading,Java,Multithreading,我有以下代码。显然,引用类不是线程安全的,因为它不保护其“Reference”属性。我如何证明我需要通过例如原子引用来保护它 当我运行以下JUnit测试时,它在两个Windows上都成功了:Intel(R)Core(TM)i5-2400 CPU@3.10GHz和Linux:Intel(R)Xeon(R)CPU X5670@2.93GHz,使用JRE 1.7.0_15 import java.util.concurrent.CountDownLatch; import org.junit.Test

我有以下代码。显然,引用类不是线程安全的,因为它不保护其“Reference”属性。我如何证明我需要通过例如原子引用来保护它

当我运行以下JUnit测试时,它在两个Windows上都成功了:Intel(R)Core(TM)i5-2400 CPU@3.10GHz和Linux:Intel(R)Xeon(R)CPU X5670@2.93GHz,使用JRE 1.7.0_15

import java.util.concurrent.CountDownLatch;
import org.junit.Test;
import static org.junit.Assert.assertTrue;

public class AssignReferenceTest {
    private static class Reference {
        private Object reference = null;

        private void setReference(Object reference) {
            this.reference = reference;
        }

        boolean hasReference() {
            return reference != null;
        }
    }

    @Test
    public void runManyTimes() throws Exception {
        for (int i = 0; i < 100000; i++) {
            testReferenceVisibilityProblem();
        }
    }

    public void testReferenceVisibilityProblem() throws Exception {
        final Reference reference = new Reference();
        final CountDownLatch latch = new CountDownLatch(1);

        Thread writeThread = new Thread(new Runnable() {
            public void run() {
                reference.setReference(new Object());
                latch.countDown();
            }
        });
        Thread readThread = new Thread(new Runnable() {
            public void run() {
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                assertTrue("Should have the reference", reference.hasReference());
            }
        });

        writeThread.start();
        readThread.start();
        writeThread.join();
        readThread.join();
    }
}
import java.util.concurrent.CountDownLatch;
导入org.junit.Test;
导入静态org.junit.Assert.assertTrue;
公共类分配引用测试{
私有静态类引用{
私有对象引用=null;
私有void setReference(对象引用){
this.reference=参考;
}
布尔hasReference(){
返回引用!=null;
}
}
@试验
public void runManyTimes()引发异常{
对于(int i=0;i<100000;i++){
testReferenceVisibilityProblem();
}
}
public void testReferenceVisibilityProblem()引发异常{
最终参考=新参考();
最终倒计时闩锁=新倒计时闩锁(1);
Thread writeThread=新线程(new Runnable(){
公开募捐{
setReference(新对象());
倒计时();
}
});
线程readThread=新线程(new Runnable(){
公开募捐{
试一试{
satch.wait();
}捕捉(中断异常e){
e、 printStackTrace();
}
assertTrue(“应该有引用”,reference.hasReference());
}
});
writeThread.start();
readThread.start();
writeThread.join();
readThread.join();
}
}

您的代码是线程安全的,因为CountDownLatch保证在
await()之前所做的每一个更改都会在之后所做的所有更改之前返回

见:

“释放”同步器方法(如Lock.unlock、Semaphore.release和CountDownLatch.countDown)之前的操作发生在另一个线程中的同一同步器对象上成功“获取”方法(如Lock.Lock、Semaphore.acquire、Condition.await和CountDownLatch.await)之后的操作之前


您的代码是线程安全的,因为CountDownLatch保证在
await()
之前所做的每一个更改都会在之后所做的所有更改之前返回

见:

“释放”同步器方法(如Lock.unlock、Semaphore.release和CountDownLatch.countDown)之前的操作发生在另一个线程中的同一同步器对象上成功“获取”方法(如Lock.Lock、Semaphore.acquire、Condition.await和CountDownLatch.await)之后的操作之前


reference.setReference(newobject())前面添加一个
sleep(1000)
怎么样如果希望测试失败?为什么你要证明它会失败?@Buurman-Thread.sleep(1000)不会让它失败。如果我不能证明问题的存在,我就不能证明我已经解决了这个问题。你的锁存器确保在测试之前总是设置了引用。用不同的对象重置它不会使测试失败,也不会设置为空。您只是将一个对象替换为另一个被assertTrue完全忽略的对象statement@MatthiasJava内存模型并不能保证您刚才所说的,比如:@Wojtek,如果您不使用闩锁在引用肯定已初始化的点上进行同步,那么这将是正确的。同步块确保语句不会发生有趣的重新排序。在
reference.setReference(new Object())前面添加
sleep(1000)
怎么样如果希望测试失败?为什么你要证明它会失败?@Buurman-Thread.sleep(1000)不会让它失败。如果我不能证明问题的存在,我就不能证明我已经解决了这个问题。你的锁存器确保在测试之前总是设置了引用。用不同的对象重置它不会使测试失败,也不会设置为空。您只是将一个对象替换为另一个被assertTrue完全忽略的对象statement@MatthiasJava内存模型并不能保证您刚才所说的,比如:@Wojtek,如果您不使用闩锁在引用肯定已初始化的点上进行同步,那么这将是正确的。同步块确保不会发生语句的有趣的重新排序。