UDP socket能否被多线程同时调用sendto来发送数据？程序里有多个线程调用同一个UDP socket的sendto操作来发送数据，目前没有做互斥，不知道这个做法是否合适。  
如果是TCP，那么肯定是需要互斥加锁的，因为TCP存在一个发送缓存，多线程一起send会有问题。但对UDP我就不太确定了，网上找了下也没有相关的讨论。
查了一下。简单说，情况是这样：

1、无论TCP还是UDP，send/sendto都是原子性的。因为它是一个系统调用，所有系统调用天然都是原子的。

2、但，在具体使用场景下，对于TCP，典型的用法是：

            #使用select/poll关注指定socket文件    while(select(files)) { #伪码，肯定不能正确运行        #socket文件可写——相当于系统缓冲区空出了若干字节（比如空闲了N个字节）            #往socket文件里面写入最多N个字节        bytes = send(file1, buf, buf_size)            #检查实际写入的字节数        if (bytes < buf_size) {            #调整缓冲区首指针，下次就不要写已经成功发送出去的数据了        } else {            #数据已经写完，可跳出循环了            break;        }            #继续等待socket可写，直到写完所有数据    }

可见，在上面这个过程中，虽然每次TCPsend调用是原子的，但每次写入字符数不定；如果多个线程同时写入，刚好在select和send之间，另一个线程也对这个socket发送了数据，引起可用空间不足，那么本地写入就只能写入半截信息，下次写入又不知道轮到谁了。换句话说，数据几乎是一定会写乱的。

换句话说，TCP send作为系统调用，对它的调用的确是原子的；但由于这个调用的特殊性，这个“原子性”是不彻底的。

因此，这里需要设计一定的保护机制，或者仅允许一个专门的线程写socket，确保数据被正确发送——但，请注意，简单的对send加锁是救不了你的。

3、对于UDP，它的情况比较特殊。只要socket可写了，那么你一定可以一次写足允许的最大UDP报文长度。

换句话说，它是真原子的，所以可以用多线程随意操作。