2012-01-29 4 views
0

У меня есть вопрос о java multi-threading.Многопоточность ленивая инициализация

У меня есть класс, который имеет доступ к нескольким потокам.

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 и Питер,

Я думаю, что следующий будет также решать проблемы безопасности нити:

public Object getObjectA() 
{ 
    Object obj = new Object() 
    obj.setProperty("prp1"); 
    return obj;                     
} 
+0

@ skaffman Я предположил, что это был заполнитель для фактического, содержательного условия – Bohemian

+0

@Bohemian вы правы –

+0

Когда вы используете поле или переменную, обычно лучше ограничить область охвата только там, где это необходимо. В этом случае это может фактически решить вашу проблему. –

ответ

0

Да.

Если два потока вызывают различные пути кода в returnObject() одновременно, она может работать getObjectB() между двумя высказываниями в getObjectA() и в конечном итоге вызова obj.setProperty("prp1"); на ObjectB.

+0

Ahh thanx SLaks. –

0

Да, это создаст проблемы (попробуйте код, чтобы увидеть, какие проблемы, но данные будут потеряны). Простейшим решением является использование блока synchronized.

+0

Привет, Питер, Как насчет того, если я пойду для публичного объекта getObjectA() { Object obj = new Object() obj.setProperty ("prp1"); return obj; } –

+0

Это должно быть хорошо. –

0

При условии, что if(true) не является жестко закодированным, так как это будет исправлять путь выполнения, где getObjA() всегда вызывается!

Да, этот код может работать в состоянии гонки, где значение obj может зависеть от порядка выполнения потока (то есть, какой порядок getObj ..() вызывается несколькими потоками).

Вы должны получить synchronize доступ к переменной obj.

0

Я думаю, что getObjectA() и getObjectB() должны быть объявлены как частные, а затем вы должны использовать синхронизированный блок внутри метода 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"); 
} 

} 

Очевидно верно условия должны заменить на какое-то условие ...

0

Я бы предложил перейти к NOT имеет форму 'obj 'как элемент данных, так как требуется одновременное обращение к нему.

Есть несколько решений:

  1. Создание объекта локально внутри функции
  2. Использовать ThreadLocal объект, который может "обручи" The 'OBJ' Данные члены
  3. Создание объекта один раз и пользователь clone() для каждого вызова локально локальному объекту и редактировать его.
0

Да, но это довольно просто исправить, так как вы заменяете 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.

Смежные вопросы