2010-10-03 6 views
1

Lorsque vous Google pour serveur java multi-thread, la plupart du temps, vous aurez une solution basée sur un schéma suivant:serveur Java multi-thread vs publication sécurité

public class MultiThreadServer implements Runnable { 
    private Socket socket; 

    MultiThreadServer(Socket socket) { 
    this.socket = socket; 
    } 

    public static void main(String args[]) throws Exception { 
    ServerSocket serverSocket = new ServerSocket(4444); 
    while (true) { 
     new Thread(new MultiThreadServer(serverSocket.accept())).start(); 
    } 
    } 

    public void run() { 
    // ... 
    PrintWriter out = new PrintWriter(socket.getOutputStream(), true); 
    BufferedReader in = new BufferedReader(
       new InputStreamReader(
       socket.getInputStream())); 
    // ... 
    } 
} 

Quel est le rapport à des idiomes de publication sécuritaires présentés dans Java Concurrency in Practice?

Pour publier un objet en toute sécurité, à la fois la référence à l'objet et l'état de l'objet doit être rendu visible à autres threads en même temps. Un objet correctement construit peut être en toute sécurité publiée par:

  • Initialiser une référence d'objet à partir un initialiseur statique.
  • Enregistrement d'une référence dans un champ volatile.
  • Enregistrement d'une référence dans un champ final.
  • Enregistrement d'une référence dans un champ correctement protégé par un verrou (synchronisé) .

Est-il vraiment sûr d'utiliser socket au sein de la méthode run() sans synchronisation supplémentaire, est-il en toute sécurité publié? S'il vous plaît écrire plus que juste oui ou pas.

Répondre

2

Oui, c'est sûr car le début du thread définit une relation arrive avant. C'est, MultiThreadServer appel constructeur arrive-avant l'exécution de la méthode run du fil.

De Java Language Specification 17.4.4-17.4.5:

Un appel pour commencer() sur un thread qui se passe, avant toute action dans le fil commencé

Précautions de Java Concurrency dans Pratique sont applicables dans le cas où l'objet est rendu accessible aux autres existants discussions, de sorte qu'ils ne sont pas applicables à ce cas.

+0

Ca a du sens, merci! – lukem00

+0

Cela signifie que si le thread a été récupéré à partir d'un pool de threads au lieu du nouveau Thread(), il ne serait pas sûr - ou est-ce que je ne comprends pas correctement? (dans ce cas marquer le champ 'socket' comme final serait suffisant?) – nos

+0

@nos:' ExecutorService' offre la même garantie explicitement dans javadoc: http://download.oracle.com/javase/6/docs/api/ java/util/concurrent/ExecutorService.html – axtavt