我有一个关于java多线程的问题。
我有一个类可以访问多个线程。
Class A
{
private Object obj;
public Object returnObject()
{
if(condition)
return getObjectA();
else
return getObjectB();
}
public Object getObjectA()
{
obj = new Object()
obj.setProperty("prp1");
}
public Object getObjectB()
{
obj = new Object()
obj.setProperty("prp2");
}
}
当有多个线程访问getObj时。。()。它是否会给"obj"状态带来问题。会有不希望的结果吗?
感谢SLaks和Peter,
我认为以下内容也将解决线程安全问题:
public Object getObjectA()
{
Object obj = new Object()
obj.setProperty("prp1");
return obj;
}
是。
如果两个线程同时调用returnObject()
中的不同代码路径,它可能会在getObjectA()
中的两个语句之间运行getObjectB()
,并最终在ObjectB上调用obj.setProperty("prp1");
。
是的,它会产生问题(试着代码看看什么样的问题,但数据会丢失)。最简单的解决方案是使用synchronized
块。
假设if(true)
不是硬编码的,因为这将修复始终调用getObjA()的执行路径!
是的,此代码可以运行到竞争条件中,其中obj
的值可以取决于线程执行的顺序(即多个线程调用getObj.()的顺序)。
您需要synchronize
对obj变量的访问权限。
是的,但这很容易修复,因为每次调用都要替换obj
,所以您显然不关心它,所以请尝试将字段obj
作为局部变量,如下所示:
Class A {
public Object returnObject() {
if (true)
return getObjectA();
return getObjectB();
}
public Object getObjectA() {
Object obj = new Object()
obj.setProperty("prp1");
return obj;
}
public Object getObjectB() {
Object obj = new Object()
obj.setProperty("prp2");
return obj;
}
}
如果这对您有效,请考虑将这些方法设置为static
。
我建议将代码更改为NOT将'obj
'作为数据成员,因为它需要同时访问。
有几种解决方案:
- 在函数内部本地创建对象
- 使用可以"包装"obj"数据成员的ThreadLocal对象
- 创建一次Object,每次本地调用本地Object时使用
clone()
并对其进行编辑
我认为getObjectA()
和getObjectB()
应该被声明为private,然后你应该在returnObject()
方法中使用一个同步块,所以类似这样的东西:
class A
{
private Object obj;
public Object returnObject()
{
Object result;
synchronized (A.class) {
result = (true) ? getObjectA() : getObjectB();
}
return result;
}
private Object getObjectA()
{
obj = new Object()
obj.setProperty("prp1");
}
private Object getObjectB()
{
obj = new Object()
obj.setProperty("prp2");
}
}
显然true条件必须替换为某些条件