我正在开发一个网络浏览器游戏,我想问一下线程安全性。 假设我们有一个域类(数据库实体)User和MyBuilding:
class User
{
public String name;
List<Building> myBuildings = new ArrayList<Building>();
}
和
class MyBuilding
{
public int buildingId;
public int level;
}
现在,用户希望得到例如建筑健康点。 我有另一个类,它存储有关那些构建规范的信息,不需要存储在数据库中,它们只是“构建规范”类,并在Web应用程序启动时从xml文件初始化。 E.g:
@Component
class BuildingSpecificationHolder
{
public List<BuildingSpecification> buildings = new ArrayList<BuildingSpecification>();
}
//下面的类不是Spring组件,只是一个简单的类
class BuildingSpecification
{
public int getHealthPointByBuildingLevel(MyBuilding usersBuilding)
{
return usersBuilding.getLevel() * 10;
}
现在我的问题是:是吗? 'public int getHealthPointByBuildingLevel(MyBuilding usersBuilding)' 线程安全?如果同时不同的用户想要构建hp,他们都可以访问 上述方法,即非弹簧对象。请注意,“BuildingSpecification”的所有方法都是只读的(用户永远不会更改构建属性),但不同的用户会将不同的“MyBuilding”参数传递给那些方法。只有拥有这些Buildings规范的类才是Spring组件。
答案 0 :(得分:4)
如果程序不包含数据争用,则程序是线程安全的。如果多个线程以一种访问顺序很重要的方式访问内存位置(例如,一个线程写入一个字段,另一个线程读取它),则会发生数据争用。
换句话说,线程安全是关于通过多个线程协调对可变状态的访问。因此,如果您只在初始化期间更改对象的状态,并且在对象可供其他线程使用之前初始化完成,则该对象非常简单。它的声音像BuildingSpecification
就是这样一个对象。
方法参数,用于特定线程对方法的特定调用,只能由该线程访问,因此始终是线程安全的(当然,如果方法参数引用对象,则可以访问该对象)通过另一个线程,即使方法参数不是)。从技术上讲,方法参数存储在线程的堆栈中,而不是所有线程共享的堆。
答案 1 :(得分:0)
从技术上讲,getHealthPointByBuildingLevel
不是线程安全的。尽管Spring初始化在启动时在单个线程中发生,但您仍可能在另一个线程中看到未初始化的值。但这不太可能。
由于您没有更改这些规范类,最简单的方法是使它们不可变:
class MyBuilding
{
public final int buildingId;
public final int level;
// constructor which initializes all fields
}