我之前还不知道这回事,把他当作经营共享了,还好火龙果指出了错误,这里表示感谢。
帖子在这。
http://topic.csdn.net/u/20090810/11/d3fd2c2e-0682-4f65-adf2-b908971b66eb.html
为了进一步弄清这个问题,我想求一个验证程序。我写了一个:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package single;/**
 *
 * @author l33187
 */
public class Single {    public static Single s = null;
    public static Object lock = new Object();
    private int a = 0;    private Single() {
        this.a = 100;
    }    public static Single getSingle() {
        if (s == null) {
            //synchronized (lock) {
                if (s == null) {
                    //Single tmp = new Single();
                    //s = tmp;
                    s = new Single();
                }
            //}
        }
        return s;
    }
    
    public static void main(String[] args){
        for(int i=0;i<50;i++){
            Thread t = new Thread(new ThreadSingle());
            t.start();
        }
    }    public static class ThreadSingle implements Runnable {        public void run() {
            try {
                int count =0;
                for(int i=0;i<10;i++){//主要时混淆代码,让后续代码更多的机会并行
                    Thread.sleep(2);
                }
                if (Single.getSingle().a != 100){
                    System.out.println("!!!初始化失败!!!!");
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
但是很可惜行不通,甚至不加同步,还是初始化成功的。线程数从10改到1000都没验证出失败来。
请教达人验证方法。

解决方案 »

  1.   

    LZ想要验证的是在多线程下,单例只会被创建一次吧?你这样验证应该是不对的,不管单例在线程中被创建多少次,只要调用Single.getSingle(),至少有一个Single被实例化,也就是说a的值是不是100只取决于你是否调用过构造方法,而构造方法是一定会被调用的,所以你在取得a的时候,它一定是100,不知道这么说是否清楚?我是这么理解的。至于验证方法,我想可以在构造函数中给a一个随机数,这样应该就可以知道是否是单例了吧?或者:public class Single {     public static Single s = null; 
        public static Object lock = new Object();
        private static int flag = 0;
        public int a = 0;     private Single() { 
            this.a = ++flag; 
        } 
    PS.LZ上面的代码a是private,难道真的可以通过?异或ing……
      

  2.   

    你理解错了,看看我的原贴就知道了http://topic.csdn.net/u/20090810/11/d3fd2c2e-0682-4f65-adf2-b908971b66eb.html 
    要验证的实际就是构造函数,文章是说,new函数将会被拆分成3个微指令的伪代码。头两个创建实例,最后一个初始化。
    这个程序就是想验证,双重锁单例是无效的。
    可是我怎么验证,都是有效的,连不加同步也有效。可能是操作系统问题,我没有环境,有没有大侠能在Linux或unix下也验证一下。
    另外,建议达人看看原贴,这里有些东西是没有写出来的。
      

  3.   

    Single() 延长时间,如 Sleep(1000)
      

  4.   

    哭啊,初始化只是一瞬间,我又改进了程序,模拟初始化n次。结果还是失败~~~
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package single;/**
     *
     * @author l33187
     */
    public class Single {    public static Single s = null;
        public static Object lock = new Object();
        private String a = null;    private Single() {
            this.a = new String("aa");
        }    public static Single getSingle() {
            if (s == null) {
                //synchronized (lock) {
                if (s == null) {
                    //Single tmp = new Single();
                    //s = tmp;
                    s = new Single();
                }
            //}
            }
            return s;
        }    public static void reset() {
            s = null;
        }    public static void main(String[] args) throws Exception {
            int count = 3;
            ThreadSingle[] t = new ThreadSingle[count];
            for (int i = 0; i < count; i++) {
                t[i] = new ThreadSingle();
                t[i].start();
            }
            for (int i = 0; i < 100; i++) {
                waitAllFinish(t);
                reset();
                //再执行模拟重新初始化
                for (int k = 0; k < count; k++) {
                    t[k].resetFinished();
                }
                synchronized (lock) {
                    lock.notifyAll();
                }
            }
            //最后设置退出
            waitAllFinish(t);
            for (int k = 0; k < count; k++) {
                t[k].singleOver = true;
                t[k].resetFinished();
            }
            synchronized (lock) {
                lock.notifyAll();
            }
        }    public static void waitAllFinish(ThreadSingle[] ts) throws Exception {
            boolean singleFinished = false;
            outer:
            while (!singleFinished) {
                Thread.sleep(100);
                for (ThreadSingle t : ts) {
                    if (!t.isSingleFinished()) {
                        break outer;
                    }
                }
                singleFinished = true;
            }
        }    public static class ThreadSingle extends Thread {        public boolean singleFinished = false;
            public boolean singleOver = false;        public boolean isSingleFinished() {
                synchronized (lock) {
                    return this.singleFinished;
                }
            }        public boolean resetFinished() {
                synchronized (lock) {
                    return singleFinished = false;
                }
            }        public void run() {
                while (!singleOver) {
                    try {
                        synchronized (lock) {
                            while (singleFinished) {
                                lock.wait();
                            }
                        }
                        int count = 0;
                        for (int i = 0; i < 10; i++) {//主要时混淆代码,让后续代码更多的机会并行                        Thread.sleep(2);
                        }
                        if (Single.getSingle().a == null) {
                            System.out.println("!!!初始化失败!!!!");
                        }
                        synchronized (lock) {
                            singleFinished = true;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }