我想知道如果两个线程同时调用同一个函数会发生什么,并且该函数是一个通过套接字发送文本的UDP客户端。
考虑到以下代码,我一直在运行它,但我还没有任何错误。我想知道它是否应该崩溃,因为线程同时使用相同的源(函数,变量,IP,端口),它们如何共享源?我可以想象下面的代码是多线程的错误用法,你能解释一下如何使用线程,以便线程只使用该函数而不使用其他线程吗?换句话说,它怎么可能是线程安全的?
作为Linux上的示例C代码:
void *thread1_fcn();
void *thread2_fcn();
void msg_send(char *message);
int main(void){
pthread_t thread1, thread2;
pthread_create( &thread1, NULL, thread1_fcn, NULL);
pthread_create( &thread2, NULL, thread2_fcn, NULL);
while(1){}
return 0;
}
void *thread1_fcn(){
while(1){
msg_send("hello");
usleep(500);
}
pthread_exit(NULL);
}
void *thread2_fcn(){
while(1){
msg_send("world");
usleep(500);
}
pthread_exit(NULL);
}
void msg_send(char message[]){
struct sockaddr_in si_other;
int s=0;
char SRV_IP[16] = "192.168.000.002";
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(12346);
si_other.sin_addr.s_addr = htonl(INADDR_ANY);
inet_aton(SRV_IP, &si_other.sin_addr);
sendto(s, message, 1000, 0, &si_other, sizeof(si_other));
close(s);
}
答案 0 :(得分:4)
您的代码没有任何问题。每个线程,即使它运行相同的代码,也有一个单独的堆栈,因此它可以使用一组独立的变量。没有共享变量。
答案 1 :(得分:3)
由于您在msg_send
内创建并关闭套接字,因此不会发生任何特殊情况。一切都会好起来的。
答案 2 :(得分:1)
您的代码调用未定义的行为,因为线程将小字符串文字作为message
参数传递,但该函数尝试从message
基址开始发送1000个字节。
由于sendto
通常是对操作系统的直接调用,否则您将通过UDP发送大量垃圾(或者更糟糕的是:安全敏感信息!),或者系统调用将检测到超出范围的内存访问并返回-1,并将errno设置为EFAULT
(可能没有发送任何数据)。
由于message
是一个字符串,你应该计算它的长度,然后只发送那个数量(有或没有空终止符;这取决于你。接收者可以从长度中重建一个空终止的字符串数据报。)
但该函数不会引发并发问题。
即使多个线程在同一个套接字上调用它,sendto
函数也是安全的。但是,如果在流套接字上执行此操作,则可能会遇到以不可预测的方式将数据交错到字节流中的问题。