如何在JAVA中使静态方法线程安全?

Ter*_*rry 6 java multithreading static-methods thread-safety

我正在创建一个Web应用程序并遇到线程安全问题.在阅读了几个类似的问题之后,我仍然对我的案子感到困惑.我正在使用java spring框架来设置REST Web服务.所有请求(Person对象的JSON)都将传递给checkIfGoodName函数,就像Checker.checkIfGoodName(person).它们都是静态方法调用.我想知道,这个功能,Checker.checkIfGoodNameTHREAD SAFE?如果没有,如何修改代码?我的代码如下:

Checker.java

public class Checker {

    public static void checkIfGoodName(Person person){

        checkingName(Person person);

    }

    private static void checkingName(Person person){

        if(person.getName()==null){
            PersonUtils.addErrorMessage(Person person, new String("Name is empty"));
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

PersonUtils.java

public class PersonUtils {

     public static void addErrorMessage(Person person, String errorMessage){

         List<Message> msg = person.getMessageList();
         if(msg!=null){
             msg.add(buildMessage(errorMessage));
         }
     }

     public static void buildMessage(String errorMessage){
         if(errorMessage != null){
             Message msg = new Message();
             msg.setMsg(errorMessage);
         } 
     }

}
Run Code Online (Sandbox Code Playgroud)

Sol*_*low 7

不要考虑使方法线程安全.线程安全是关于保护数据的完整性.更具体地说,它是在一些其他线程正在改变数据的过程中阻止线程访问数据.

您的PersonUtils.addErrorMessage(person, message)方法修改List属于Person实例的实例.对列表的访问应该是synchronized如果相同的列表可以由两个不同的线程修改,或者它可以由一个线程修改并由其他线程访问.

将项添加到列表需要几个步骤,如果线程A能够在线程B执行了一些但不是所有步骤的某个点上看到它,则列表几乎肯定会看起来处于非法状态.如果两个线程同时尝试修改列表,那就更糟了:这可能会使列表处于永久的非法状态.

即使在同一个Person实例上运行的线程实际上并不同时执行,您仍然需要同步.原因是,如果没有同步,计算机硬件和操作系统不保证一个线程在内存中进行的更改将立即对其他线程可见.但是,synchronized来救你:

在线程B进入块之后,线程A在离开synchronized(foo)块之前所做的任何更改都将对线程B可见synchronized(foo).

如果不同的线程访问同一个Person实例,那么最简单的事情就是在addErrorMessage(...)方法中对Person对象进行同步:

  public static void addErrorMessage(Person person, String errorMessage){
      synchronized(person) {
          List<Message> msg = person.getMessageList();
          if(msg!=null){
             msg.add(buildMessage(errorMessage));
          }
      }
  }
Run Code Online (Sandbox Code Playgroud)

  • @Mikhail示例中_explicit_的所有变量都是本地的,但示例调用方法; PersonUtils.addErrorMessage(...),person.getMessageList(),msg.add(...).你能肯定地说这些方法都没有涉及局部变量吗?如果这是真的,他们会有什么用处? (2认同)