Java Synchronized方法未锁定对象

时间:2016-06-04 03:37:17

标签: java

我写了一个java程序来为文件中的每一行生成唯一的id。可能有多个作业运行相同的程序以获得唯一的ID。对于任何文件中的每一行,此id必须是唯一的。我试图通过将值序列化到文件来实现此目的。由于多个作业将使用此程序,因此我使方法同步。代码适用于单个作业,但是当尝试同时运行多个作业时,同步方法失败。当有一个已经运行时,看起来在同一个对象上再次调用方法。为什么synchronized方法没有锁定对象?

下面是我写的id生成代码 -

public class CreateId2 implements Serializable {

private static final long serialVersionUID = 1L;
private long i;

public synchronized long idGenerate() {

    long k = this.generateId(this);
    return k;

}
private long generateId(CreateId2 id){

    long returnedVal = id.getI();
    try {
    returnedVal = id.readObject();
    //System.out.println("previous modiefiied returnedVal is" + returnedVal);
    } catch (FileNotFoundException  ex) {
        id.setI(200L); //start from 200 for the first time
        returnedVal=id.getI();
    } catch (Exception ex2) {
        ex2.printStackTrace();
    }
    returnedVal = returnedVal +1;
    id.setI(returnedVal);
    //System.out.println("returnedVal is " + returnedVal);
    try {
    id.saveObject(id);
    } catch (Exception ex3) {
        ex3.printStackTrace();

        }
    return returnedVal;
}

public void saveObject(CreateId2 id) throws IOException{
    //System.out.println("saving object " + id.getI());
    File savedFileName = new File("C:\\Users\\sam\\Desktop\\tests\\test.ser");
    FileOutputStream savedOutput = new FileOutputStream(savedFileName);
    ObjectOutputStream oos = new ObjectOutputStream(savedOutput);

    oos.writeObject(id);
    oos.flush();
    // close the writing.
    oos.close();
    //System.out.println("saved. value is " + id.getI());
}

public long readObject() throws IOException, ClassNotFoundException{
    //System.out.println("read object is called. value is " + ci2.getI());

    File savedFileName = new File("C:\\Users\\sam\\Desktop\\tests\\test.ser");
    FileInputStream savedInput = new FileInputStream(savedFileName);
    ObjectInputStream ois = new ObjectInputStream(savedInput);

    //long val = Long.parseLong(ois.readObject().toString());

    CreateId2 ci2 = (CreateId2) ois.readObject();
    //System.out.println("value of valtemp " + ci2.getI());
    long val = Long.valueOf(ci2.getI());

    ois.close();
    return val;
    // close the writing.

}

public  long getI() {
    return i;
}

public void setI(long i) {
    this.i = i;
    //CreateId2.i = i;
}

// setter methods

private static CreateId2 instance = null;
private CreateId2() { }
public static CreateId2 getInstance() {
   if (instance == null) {
       instance = new CreateId2();
   }
   return instance;
}

}

我这样称呼这个方法 -

CreateId2 id = CreateId2.getInstance();
long j = id.idGenerate();

当我同时调用此方法时,我得到以下错误。生成的ID也不再是唯一的。

java.io.EOFException
    at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2325)
    at java.io.ObjectInputStream$BlockDataInputStream.readUnsignedShort(ObjectInputStream.java:2806)
    at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2864)
    at java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1072)
    at java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:704)
    at java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:830)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1601)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at helperPackage.CreateId2.readObject(CreateId2.java:66)
    at helperPackage.CreateId2.generateId(CreateId2.java:23)
    at textFile.RandomTest.main(RandomTest.java:18)

2 个答案:

答案 0 :(得分:0)

synchronized仅适用于同一JVM中同一对象同步的两个类。如果您有多个监视器对象实例,或者在多个JVM中运行,或者在批处理系统下,每个作业都有自己的类加载器,那么synchronized将无法正常工作。使用type-4 UUID,它是随机的128位值和"保证"独一无二。

(即使你在宇宙时代每秒产生100万UUID,也很难发生碰撞)

答案 1 :(得分:0)

吉姆加里森已经回答了许多可能导致问题的情况。我想再添加一个可能的(和常见的)错误可能导致此问题:

idGenerate()是线程安全的,但是你的单例构造函数不是线程安全的。您可以创建许多 CreateId2 对象。见an example of a thread-safe Singleton