4

I have 2 classes where I have one to send commands to a socket, another which receives (and sometimes answers commands) .

Do I have to synchronize this? Or is this not necessary?

Both classes run in their own threads with the socket object passed down to each of them as argument upon thread.start();

Is this the proper way to do it or could I do something more efficient?

Would this have chances of causing errors? The sending part:

    public void run(){
        send_chatline("roomf");

        int vvv = 0;
        while (this.socket.isConnected()){
            try{
                Thread.sleep(10000);
                vvv++;

                Thread.sleep(10000);
                send_chatline("alive");

                Thread.sleep(10000);

                if (vvv == 1) {
                    this.socket.flush();
                    this.socket.send("T,-1," + this.playerid * 3);
                    this.socket.flush();
                }
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

But remember! The recieveFromSock class also writes sometimes when specific commands appear.

The only function of sendTosock is to keep the connection alive (being able to remain online).

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
Stackie Overflower
  • 201
  • 1
  • 6
  • 14
  • 1
    Show the code you are using to write to the socket. – Jivings Mar 28 '12 at 09:34
  • possible duplicate of [in what way is java.net.Socket threadsafe?](http://stackoverflow.com/questions/6672413/in-what-way-is-java-net-socket-threadsafe) – user207421 Mar 28 '12 at 10:01

4 Answers4

3

The only guarantee you have is that a byte sent, is sent once, and that a byte read is read once. Others may say that the synchronization is taken care of by the runtime-library, or the underlying operating system. Any such statement is runtime-implementation dependent and/or operating system dependent (and should in my opinion be disregarded from).

So, if you have one thread reading from the socket, and one thread writing to the socket, you should be fine without synchronization.

If more than one thread may write to the socket, you should synchronize their actions to make sure the output sent from the two threads doesn't get interleaved.

Same applies if two threads read from the socket. You should synchronize the reads to make sure that data read by one thread doesn't have "gaps" due to reads of another thread.

Similar question, same conclusion:

Community
  • 1
  • 1
aioobe
  • 413,195
  • 112
  • 811
  • 826
1

Do I have to synchronize this?

No. SocketImpl has its own internal synchronization. You won't be surprised to learn that sending isn't synchronized but receiving is.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    Do you have any references for this? Reading [the documentation](http://docs.oracle.com/javase/6/docs/api/java/net/SocketImpl.html) (which should be the first source of information unless you're interested in some implementation specific details) I find nothing regarding threads or synchronization. – aioobe Mar 28 '12 at 09:38
  • @aioobe `synchronized` doesn't show up in the Javadoc. But it's in the source code all right ;) In any case it makes sense. A socket read is atomic anyway all the way down to the kernel, but a socket write needs to be synchronized against other socket writes for reasons that would appear if you delved all the way into the native code. – user207421 Mar 28 '12 at 09:41
  • 2
    Relying on assumptions on internal, undocumented features seems like a really bad idea to me. Unless feature is documented or part of the contract in some other way, the code shouldn't rely on it. – aioobe Mar 28 '12 at 09:46
  • @aioobe So in that case do the synchronization yourself, on the socket. It's not difficult. However the answer to your question remains the same. You don't have to synchronize. – user207421 Mar 28 '12 at 09:48
1

You don't need to synchronize, as the synchronization is done on the socket. The question is: are the two classes/threads communicating through sockets living in the same JVM? If so, there are several more efficient options, the most simple being having a BlockingQueue where the sender class adds its commands and the receiver takes them.

michele b
  • 1,825
  • 2
  • 20
  • 26
0

I was curious too for the nio classes and it IS synchronized(for nio only). Just look at the write method here in the sun JVM code

http://www.docjar.com/html/api/sun/nio/ch/SocketChannelImpl.java.html

Checking the old i/o socket code however shows no synchronization though there is an acquireFD and releaseFD...but no sycnhronization there...that appears to prevent a close until all writes on all threads are done(it is like they assume writes from multiple threads are okay in every OS...but I don't know if that is true OR they synchronize in the JVM native code so the developer knows they can do that)....we would need a JVM developer to tell us if there is a synch block in the windows JVM, linux JVM and mac JVM, etc. etc....

private void socketWrite(byte b[], int off, int len) throws IOException {

    if (len <= 0 || off < 0 || off + len > b.length) {
        if (len == 0) {
            return;
        }
        throw new ArrayIndexOutOfBoundsException();
    }

    FileDescriptor fd = impl.acquireFD();
    try {
        socketWrite0(fd, b, off, len);
    } catch (SocketException se) {
        if (se instanceof sun.net.ConnectionResetException) {
            impl.setConnectionResetPending();
            se = new SocketException("Connection reset");
        }
        if (impl.isClosedOrPending()) {
            throw new SocketException("Socket closed");
        } else {
            throw se;
        }
    } finally {
        impl.releaseFD();
    }
} 
Dean Hiller
  • 19,235
  • 25
  • 129
  • 212