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.
Yes, it’s safe because start of the thread defines a happens-before relation. That is,
MultiThreadServerconstructor call happens-before execution of the thread’srunmethod.From Java Language Specification 17.4.4-17.4.5:
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.