在java中对字符串方法参数同步io操作?

在java中对字符串方法参数同步io操作?,java,multithreading,synchronization,io,Java,Multithreading,Synchronization,Io,基本上,我有一个包含两个方法的类:一个用于将对象序列化为XML文件,另一个用于从XML读取对象。 以下是还原对象的方法中的同步部分示例: public T restore(String from) throws Exception { // variables declaration synchronized (from) { try { decoder = new XMLDecoder(new Buffe

基本上,我有一个包含两个方法的类:一个用于将对象序列化为XML文件,另一个用于从XML读取对象。 以下是还原对象的方法中的同步部分示例:

    public T restore(String from) throws Exception {
     // variables declaration
        synchronized (from) {
            try {
                decoder = new XMLDecoder(new BufferedInputStream(
                        new FileInputStream(from)));
                restoredItem = decoder.readObject();
                decoder.close();
            } catch (Exception e) {
                logger.warning("file not found or smth: " + from);
                throw new Exception(e);
            }
        }
    // try to cast it
    }
序列化对象时也会采用类似的方法。现在,当我创建一个单元测试,然后创建10个线程,每个线程尝试序列化并立即读取布尔值或字符串时,它将无法显示发生了ClassCastException。这让我觉得序列化是错误的(在单线程环境中一切正常)。如果您一直支持我到现在:),以下是我需要您帮助的两个问题:

  • 同步传递给方法的字符串参数(考虑到java中有一个字符串池)有意义吗?顺便说一句,我已经尝试在XMLSerializer类本身上进行同步,结果保持不变
  • 如何正确同步单个文件上的io操作

  • 鉴于代码的某些部分丢失,我敢打赌问题在于在字符串上进行同步。您不能随意假定字符串是池化的(这将破坏您的同步方案)

    最好的方法是添加一个将键(字符串)与其实际同步对象关联的映射


    除此之外,我建议使用多线程测试,看看是什么导致它失败。例如,如果让所有线程只存储字符串值(而不是字符串或beooleans),测试是否仍然失败?

    鉴于代码的某些部分丢失,我敢打赌问题在于对字符串进行同步。您不能随意假定字符串是池化的(这将破坏您的同步方案)

    最好的方法是添加一个将键(字符串)与其实际同步对象关联的映射


    除此之外,我建议使用多线程测试,看看是什么导致它失败。例如,如果让所有线程只存储字符串值(而不是字符串或beooleans),测试是否仍然失败?

    这种方法存在许多问题

  • 除非您调用了String.intern,否则您的from字符串可能与您正在调用的另一个from字符串不同。依赖内部java字符串缓存的行为不是很健壮

  • 如果您没有在finally块中正确地处理XMLDecoder,则在该调用期间引发的任何异常都将泄漏与该FileInputStream关联的文件描述

  • 您不需要在另一个异常(e)中封装e,您可以直接抛出e,因为您已经声明了封闭方法也会抛出异常

  • 捕获/引发异常是一种代码气味。是的,它是IOException的一个超类,以及可能引发的任何XML解码异常,但它也是一个超类,包含许多其他您可能不想捕获的东西,例如NullPointerException

  • 要回答您的问题,如何序列化对共享文件的访问以确保其不被多个线程使用是一个棘手的问题。FileChannel.lock()在JVM中不起作用,它们只是锁定文件,防止机器中的其他进程修改文件

    我的方法是去掉这个类中的任何锁定,并将它包装成能够意识到代码线程问题的东西

    我也不会传递字符串作为文件名,而是传递一个文件,它使您能够使用File.createTempFile(2)在编写xml和读取xml之间创建不透明的文件名


    最后,是要同步访问共享文件,还是在检测到对同一文件的多次访问时失败

    这种方法存在许多问题

  • 除非您调用了String.intern,否则您的from字符串可能与您正在调用的另一个from字符串不同。依赖内部java字符串缓存的行为不是很健壮

  • 如果您没有在finally块中正确地处理XMLDecoder,则在该调用期间引发的任何异常都将泄漏与该FileInputStream关联的文件描述

  • 您不需要在另一个异常(e)中封装e,您可以直接抛出e,因为您已经声明了封闭方法也会抛出异常

  • 捕获/引发异常是一种代码气味。是的,它是IOException的一个超类,以及可能引发的任何XML解码异常,但它也是一个超类,包含许多其他您可能不想捕获的东西,例如NullPointerException

  • 要回答您的问题,如何序列化对共享文件的访问以确保其不被多个线程使用是一个棘手的问题。FileChannel.lock()在JVM中不起作用,它们只是锁定文件,防止机器中的其他进程修改文件

    我的方法是去掉这个类中的任何锁定,并将它包装成能够意识到代码线程问题的东西

    我也不会传递字符串作为文件名,而是传递一个文件,它使您能够使用File.createTempFile(2)在编写xml和读取xml之间创建不透明的文件名


    最后,是要同步访问共享文件,还是在检测到对同一文件的多次访问时失败

    一个字符串不能构成一个好的互斥体,但可以用来创建一个:。

    一个字符串不能构成一个好的互斥体,但可以用来创建一个:。

    1。 是的,可以在字符串上同步,但是需要在字符串上同步。为了始终得到相同的对象

    StringBuffer sb = new StringBuffer(); sb.append("a").append("b");
    String a = new String(sb.toString());
    String b = new String(sb.toString());
    a == b; //false
    a.equals(b); //true
    a.intern() == b.intern(); //true
    
    由于要在同一个监视器上同步,因此需要intern()

    二,。 您可能不希望在字符串上进行同步,因为它可能在其他地方、代码内部、第三方或JRE中进行同步。我会怎么做,我