2013-02-25 21 views
7

Powiedzmy mam następujący,Czy ciąg odbierania/ustawiania wątków jest bezpieczny?

public class Foo{ 
    private String bar; 

    public String getBar(){ 
     return bar; 
    } 

    public void setBar(String bar){ 
     this.bar = bar; 
    } 
} 

Czy metody te automatycznie threadsafe powodu niezmiennego charakteru klasy String, lub wymagane jest jakiś mechanizm blokujący?

+2

Zakładam, że masz na myśli 'String' w setera. –

+0

@ TheodorosChatzigiannakis, tak, mój błąd! Naprawiony. – mre

+1

Podobne pytanie C#: http://stackoverflow.com/questions/3595114/why-are-immutable-objects-thread-safe – PermGenError

Odpowiedz

18

Nie, to nie jest bezpieczne dla wątków. Foo jest zmienny, więc jeśli chcesz mieć pewność, że różne wątki zobaczyć tę samą wartość bar - czyli konsystencję - albo:

  • Marka barvolatile lub
  • Bądź metody synchronized lub
  • Użyj numeru AtomicReference<String>.

Odczyty i zapisy o bar same są atomowe, ale atomowość nie jest bezpieczna.

http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html


Dla pokrycia dogłębnej współbieżności Java, chwyć kopię Java Concurrency in Practice (aka JCIP).

+4

+1 Lub po prostu zadeklaruj 'bar' jako' final', więc referencji nie można ponownie przypisać do innej wartości.Oczywiście nie będzie wtedy ustawiacza :) –

+1

To jest niezmienne. W takim przypadku nie trzeba ustawiać. I musisz dostarczyć konstruktora, aby zainicjować wartość, ponieważ nie możesz go zmienić po wyjściu z konstruktora w takim przypadku. – duffymo

+0

... Czy z ciekawości, czy któryś z nich rzeczywiście ma znaczenie? Chodzi mi o to, że jeśli twój rzeczywisty problem jest stanem wyścigowym, to nadal może się zdarzyć, pomimo 'volatile' lub' synchronized' - po prostu zmniejsza "okno", w którym może się zdarzyć, prawda? Czy może czegoś tutaj brakuje? –

4

Nie, nie jest bezpieczne.

To zachowanie Foo zmiennego; Niezmienność łańcucha nie ma znaczenia dla Foo.

public class Foo{ 
    private String bar; 

    public synchronized String getBar(){ 
     return bar; 
    } 

    public synchronized void setBar(String bar){ 
     this.bar = bar; 
    } 
} 
+0

+1 Co z synchronizacją 'getBar()'? Może jakiś wątek ustawia nową wartość na 'bar', podczas gdy inne wątki czytają' bar'. –

+0

Przepraszam, nie masz dla mnie żadnego sensu. Myślę, że twoje komentarze tylko mylą ten problem. – duffymo

+0

@duffymo robi niezsynchronizowany getter z synchronizowanym ustawiaczem gwarantującym spójność między wątkami? –

7

Ustawiasz odniesienia, i jako takie niezmienność String nie wchodzi w grę. Nie wpływasz na zawartość String.

3

Nie, to nie jest bezpieczne dla wątków.

Podczas gdy String jest niezmienny, problem pochodzi z pola Foo. Aby było to bardziej oczywiste, rozważmy na przykład metodę, której zadaniem byłoby dołączenie (zamiast zastąpienia) wartości bar. Gdy zostanie wywołany z wielu wątków, niektóre zapisy mogą zostać utracone. To samo (utracone zapisy) może się zdarzyć również z twoim prostym seterem, nawet jeśli nie jest to w tym przypadku oczywiste.

Powiązane problemy