首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不通过双重锁定检查的java代码

不通过双重锁定检查的java代码
EN

Stack Overflow用户
提问于 2016-01-15 07:42:01
回答 2查看 143关注 0票数 0

备注:我知道在java 5之前(2004年给出),在java中双重检查锁会失败,甚至在“”字段中添加“”。在java 5之后,易失性语义已经正确地用于双重检查锁。我还知道,如果没有“易失性”,则双重检查锁将失败。即使在java5之后,也是由于无序执行造成的.但是,我的问题是:如何编写代码来证明(双重检查锁将在没有“易失性”的情况下失败)?

我读过许多文章,指出在java中双重检查锁将失败,因此我认为下面的代码(试图获取SocketFactory的单例实例)将失败(因为“实例”字段不易失性):

代码语言:javascript
复制
  private static SocketFactory instance  = null;
  private static SocketFactory getInstance() {
      if (instance == null) {
         synchronized (SocketFactory.class){
            if (instance == null){
               instance = new SocketFactory(); // line 1
            }
         }
      }
      return instance;
   }

但是,问题是,如果上面的代码会失败,我如何证明呢?我试图在下面编写代码(我认为,如果第1行将被重新排序,“实例”引用可能指向SocketFactory对象,而“构造”字段为"false"):

代码语言:javascript
复制
import java.io.*;
import java.nio.*;
import java.nio.file.*;

public class TIJ_doubleCheckingLock {

    static TIJ_doubleCheckingLock instance;

    private Object lock;

    private boolean constructed = false;

    {   
        constructed = false;
    }

    private TIJ_doubleCheckingLock() {
        try{
            Thread.sleep(10000);
        } catch(Exception e) {
        }
        constructed = true;
    }

    static TIJ_doubleCheckingLock getInstance() {
        if (instance == null) {
            synchronized (TIJ_doubleCheckingLock.class) {
                try{
                    Thread.sleep(1000);
                } catch(Exception e) {

                }
                if(instance == null) {
                    instance = new TIJ_doubleCheckingLock();
                }
            }
        }
        return instance;
    }

    public static void main(String args[]) {
        class MyThread extends Thread {
                @Override
                public void run() {

                    TIJ_doubleCheckingLock instance = TIJ_doubleCheckingLock.getInstance();
                    String fileName = "TIJ_doubleCheckingLockResult.txt";
                    java.io.File file = new File(fileName);
                    try {
                        if(!instance.constructed) {
                            java.nio.file.Files.write(Paths.get(file.toURI()), (instance.constructed+"").
                                    getBytes("utf-8"), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
                        }
                    } catch (Exception e) {
                    }
                }

        }

        Thread firstThread = new MyThread();
        firstThread.start();

        try{
            Thread.sleep(5000);
        } catch(Exception e) {}


        for(int i=0;i<10;i++) {
            Thread thread = new MyThread(); 
            thread.start();
        }
    }
}

但我从未在txt文件中看到"false“。那么,我如何证明双重检查锁会失败呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-15 07:53:32

双重检查锁定在Java中被破坏。您的代码在Java 5和更高版本中运行良好。JVM从那时起就得到了一个新记忆模型

此外,您的代码还需要volatile关键字。

代码语言:javascript
复制
private static volatile SocketFactory instance;
票数 1
EN

Stack Overflow用户

发布于 2016-01-15 08:16:20

您需要知道我的代码在同步中的区别:

代码语言:javascript
复制
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * @author heyunxia (love3400wind@163.com)
 * @version 1.0
 * @since 2016-01-15 下午3:50
 */
public class SocketFactoryTest {

    public static void main(String[] args) {
        SocketFactoryTest test = new SocketFactoryTest();
        test.run();

    }

    private static final int COUNTER = 20;

    CyclicBarrier barrier = new CyclicBarrier(COUNTER);

    public void run(){
        for(int i=0; i<COUNTER; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    SocketFactory.getInstance(barrier);
                }
            }).start();
        }
    }

}


class SocketFactory {
    private static SocketFactory instance = null;

    public static SocketFactory getInstance(CyclicBarrier barrier) {
        if (instance == null) {
            try {
                barrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            synchronized (SocketFactory.class) {
                // option 1
                instance = new SocketFactory();
                System.out.println(Thread.currentThread().getName() + "***");

                /*
                // option 2
                if (instance == null) {
                    System.out.println(Thread.currentThread().getName() + "***");
                    instance = new SocketFactory();
                }else {
                    System.out.println(Thread.currentThread().getName() + "-have already instanced...");
                }*/
            }
        }
        return instance;
    }
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34806348

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档