views:

49

answers:

1

When you google for multi-threaded java server, most of the time you'll get a solution based on a following pattern:

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()));
    // ...
  }
}

How does that relate to safe publication idioms presented in Java Concurrency in Practice?

To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time. A properly constructed object can be safely published by:

  • Initializing an object reference from a static initializer.
  • Storing a reference to it into a volatile field.
  • Storing a reference to it into a final field.
  • Storing a reference to it into a field that is properly guarded by a (synchronized) lock.

Is it really safe to use socket within run() method without any extra synchronization, is it safely published? Please do write more than just yes or no.

+2  A: 

Yes, it's safe because start of the thread defines a happens-before relation. That is, MultiThreadServer constructor call happens-before execution of the thread's run method.

From Java Language Specification 17.4.4-17.4.5:

A call to start() on a thread happens-before any actions in the started thread

Precautions from Java Concurrency in Practice are applicable in the case when the object is made accessible to other existing threads, so they are not applicable to this case.

axtavt
Makes sense, thank you!
lukem00
This means if the thread was fetched from a thread-pool instead of the new Thread() there, it would not be safe - or am I not getting that correctly ? (in which case marking the `socket` field as final would be sufficient ?)
nos
@nos: `ExecutorService` offers the same guarantee explicitly in javadoc: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html
axtavt