donet8 发表于 2012-08-06 15:15

synchronized关键字在运行时导致了空指针错误?

我写了一个很简单的Singleton,用synchronized关键字来做inst实例引用的访问保护:
public class Revert {
        public static void main(String[] args) {
                Revert.Singleton.GetInstance();
        }
        static class Singleton{
                private static Singleton inst=null;
                public static Singleton GetInstance(){
                        if(inst==null){
                                synchronized(inst){//JVM memory barrier
                                        inst=new Singleton();
                                }
                        }
                        return inst;
                }
                Singleton(){System.out.println("ctor");}
        }
}
问题是,我一致性就报空指针错误。如果我调试的话,发现调试器会在synchronized那句话那里停留两次,但是根本就不执行inst=new Singleton();这句话。

我的代码有什么问题? 还是我理解的就不对?
我用Eclipse+jdk1.6

isaacxu 发表于 2012-08-06 15:15

本帖最后由 isaacxu 于 2012-08-07 03:36 编辑

也许是讲的不清楚,还是烦请阅读《Effective Java》2nd里,“Item 3: Enforce the singleton property with a private constructor or an enum type”的相关内容,原文:“As of release 1.5, there is a third approach to implementing singletons. Simply make an enum type with one element:”
Joshua Bloch给出的代码:// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}写了一个Enum Singleton的Junit测试用例,在Eclipse里选择File->New->Junit Test Case,可以生成相应的Junit测试文件,然后,Run as Junit Test 就可以了。/**
* File:EnumSingleton.java
* ---------------------------
* for test Enum Singleton
*/
package org.cudemo;

/**
* @author isaacxu
*
*/
public enum EnumSingleton {

        INSTANCE;
       
        private String name;

        // Private constructor can prevents instant from other classes
        private EnumSingleton() {
        }
    //set a obj name
        public void setName(String name) {
                this.name = name;
        }
    //get a obj name
        public String getName() {
                return name;
        }

}

Junit 测试用例/**
* File:EnumSingletonTest.java
* ------------------------------
* This a junit test case for test EnumSingleton
*/
package org.cudemo;

import static org.junit.Assert.*;

import org.junit.Test;

public class EnumSingletonTest {

        @Test
        public void test() {
                EnumSingleton firstObj = EnumSingleton.INSTANCE;
          firstObj.setName("Enum");
          EnumSingleton secondObj = EnumSingleton.INSTANCE;
          secondObj.setName("Singleton");
          assertTrue(firstObj == secondObj);
          assertEquals("Singleton", firstObj.getName());
          assertEquals("Singleton", secondObj.getName());
          
        }

}

isaacxu 发表于 2012-08-06 17:58

/**
* File:MyRevert.java
* ----------------------
*         Please read Item 3 in the 2nd Edition of <Effective Java>,Bloch explains three ways of implementing
* a singleton in Java, the best is “Enum as Singleton”.Joshua Bloch is aka Josh Bloch,you can see his
* write code in OpenJdk source code.(e.g.Collections.java)
*/
package org.cudemo;

/**
* @author isaacxu
*
*/
public class MyRevert {

        /**
       * @param args
       */
        public static void main(String[] args) {
               
                MyRevert.Singleton.getInstance();
                MyRevert.MyNewSingleton.gotIt();

        }
        /**
       * before Java1.5
       * @author isaacxu
       *
       */
        public static class Singleton {
                private static Singleton uniqInstance;

                private Singleton() {
                       
                }

                public static synchronized Singleton getInstance() {
                        if (uniqInstance == null) {
                                uniqInstance = new Singleton();
                        }
                        System.out.println("Hi,I am old java Singleton");
                        return uniqInstance;
                }
               
        }
        /**
       * after Java1.6
       */
        public static enum MyNewSingleton {
                INSTANCE;
                public static void gotIt(){
                        System.out.println("Hi,I am the best Singleton!");
                }
       
        }

}

donet8 发表于 2012-08-06 22:45

isaacxu 发表于 2012-08-06 17:58 static/image/common/back.gif


你是说,java1.6以后声明一个INSTANCE就相当于声明了一个Singleton类型? 这么神奇? 我百度了半天Java 1.6 INSTANCE没找到什么有用的信息啊。
页: [1]
查看完整版本: synchronized关键字在运行时导致了空指针错误?