我正在创建一个Web应用程序并遇到线程安全问题.在阅读了几个类似的问题之后,我仍然对我的案子感到困惑.我正在使用
java spring框架来设置REST Web服务.所有请求(Person对象的
JSON)都将传递给checkIfGoodName函数,如Checker.checkIfGoodName(person).它们都是静态方法调用.我想知道,是这个函数,Checker.checkIfGoodName THREAD 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")); } } }
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); } } }
解决方法
不要考虑使方法线程安全.线程安全是关于保护数据的完整性.更具体地说,它是在一些其他线程正在改变数据的过程中阻止线程访问数据.
PersonUtils.addErrorMessage(person,message)方法修改属于Person实例的List实例.应该同步对列表的访问如果相同的列表可以由两个不同的线程修改,或者它可以由一个线程修改并由其他线程访问.
将项添加到列表需要几个步骤,如果线程A能够在线程B执行了一些但不是所有步骤的某个点上看到它,则列表几乎肯定会看起来处于非法状态.如果两个线程同时尝试修改列表,那就更糟了:这可能会使列表处于永久的非法状态.
即使在同一个Person实例上运行的线程实际上并不同时执行,您仍然需要同步.原因是,如果没有同步,计算机硬件和操作系统不保证一个线程在内存中进行的更改将立即对其他线程可见.但是,同步来救你:
在线程B进入同步(foo)块之后,线程A在离开同步(foo)块之前所做的任何更改都将对线程B可见.
如果不同的线程访问同一个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)); } } }