-1

The Go internal/poll/fd_unix.go code is here

// Write implements io.Writer.
func (fd *FD) Write(p []byte) (int, error) {
    if err := fd.writeLock(); err != nil {
        return 0, err
    }
    defer fd.writeUnlock()
    ......
}

the java code java.net.SocketOutputStream#socketWrite is here

 private void socketWrite(byte b[], int off, int len) throws IOException {
        if (len <= 0 || off < 0 || len > b.length - off) {
            if (len == 0) {
                return;
            }
            throw new ArrayIndexOutOfBoundsException("len == " + len
                    + " off == " + off + " buffer length == " + b.length);
        }

        FileDescriptor fd = impl.acquireFD();
        try {
            socketWrite0(fd, b, off, len);
        } catch (SocketException se) {
        ......

I don't know why we need to lock that. Another question is the syscall.Write equivalent to <unistd.h> write in C?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
tiddar Z
  • 9
  • 3
  • 4
    Well, what would you want to happen if two threads invoke this method concurrently? – Hulk Dec 10 '20 at 08:07
  • I once wrote similar code in C, using 4 threads to write to a socket, but the sequence read by another thread is correct,so I think this `write` syscall itself is thread safe. – tiddar Z Dec 10 '20 at 08:16
  • 2
    Can you _guarantee_ that for all possible supported platforms now or in the future? Is such behavior _documented_ or just an implementation detail? – Slaw Dec 10 '20 at 08:28
  • I seem to understand. What do you mean is that it is possible that the `write` of some platforms does not guarantee similar atomicity characteristics? – tiddar Z Dec 10 '20 at 08:42
  • 1
    "Another question is the syscall.Write equivalent to write in C?" -- This should be a separate question. – Jonathan Hall Dec 10 '20 at 08:47
  • 1
    [This answer](https://stackoverflow.com/a/65214682/13860) is particularly relevant, although talking about a slightly different situation (but the underlying principles are mostly the same). – Jonathan Hall Dec 10 '20 at 08:56
  • @Flimzy Yes, that question also helped me. Thank you – tiddar Z Dec 10 '20 at 10:04

2 Answers2

3

Well, only answering for the Java part:

As we are already talking about implementation details, why stop at the Java level? The C Source code for OpenJdk implementation of the native method socketWrite0 spans ~70 lines of code and is clearly not atomic. It does things like allocating and deallocating memory using malloc and free, among other things, and involves quite a bit of non-trivial logic. Whether or not the NET_Send function it invokes to actually send data directly translates to a syscall on every supported platform hardly matters anymore, at that point.

The main point is: the implementation invokes this NET_Send-function in a loop. So whether or not this is threadsafe individually, if it is invoked concurrently by multiple threads, the output will be interleaved (best case).

Hulk
  • 6,399
  • 1
  • 30
  • 52
  • ohh, than you so much ,I learned about this through your answer, and go should also be the reason. Because I found that Go also calls syscall.Write cyclically in the code below. ```for { max := len(p) if fd.IsStream && max-nn> maxRW { max = nn + maxRW } n, err := ignoringEINTR(func() (int, error) {return syscall.Write(fd.Sysfd, p[nn:max]) }) if n> 0 { nn += n }``` – tiddar Z Dec 10 '20 at 09:14
1

Okay, Suppose there is no locking mechanism and two concurrent threads/processes are writing some data to a socket. Let's take an oversimplified example.

Java application wants to write: "Hello! How are you?".

Go application wants to write: "See you later."

Both of these apps are trying to write at the same time.

The output that you expect is:

Hello! How are you?
See you later.

However, there is a high possibility that you would get something like this.

HellSee o! How  See you are later.
 you?

Whenever a resource is shared across different processes/threads and there is no locking mechanism in place. There is a high possibility to encounter inconsistent and unexpected behavior.

Navin M
  • 136
  • 1
  • 1
  • 3
  • thank you for anwser but I know that if there is no protection/lock on a socket/fd,the write byte sequence will be messy。I probably understand there is a write buffer in kernel when write to some socket,Isn't this buffer thread safe? – tiddar Z Dec 10 '20 at 08:48
  • Doesn't matter if the buffer is thread-safe, concurrent writes to the buffer will still be interleaved, so the buffer will contain interleaved data. The fact that the buffer exists also doesn't mean that it's thread-safe; it might or might not be, as an implementation detail. – Adrian Dec 10 '20 at 14:28