如果多个pthread使用同一个函数会发生什么?

8
我想知道如果两个线程同时调用同一个函数,而这个函数是以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);
}

2
调用同一函数没有问题(每个线程都有自己独立的执行上下文和堆栈)。访问共享状态(包括库调用中的共享状态)可能会出现问题-请考虑自我分析代码以查看是否存在共享状态,并围绕此重点提出问题。 - user2246674
1
自动变量的美妙之处在于一切都可以自动运行。 - Kerrek SB
1
thread1_fcn()thread12_fcn() 应该仍然声明为接受 void * 参数,以匹配 pthread_create() 的期望。 - jxh
3个回答

6

您的代码没有任何问题。每个线程,即使运行相同的代码,都有一个独立的堆栈,因此它处理的变量集也是独立的。没有共享的变量。


3

由于您在msg_send内部创建并关闭了套接字,因此不会发生任何特殊情况。一切都将正常工作。


1
你的代码调用了未定义的行为,因为线程将小字符串文字作为"message"参数传递,但函数试图发送从"message"基地址开始的1000个字节。
由于"sendto"通常是对操作系统的直接调用,因此您将通过UDP发送大量垃圾(或更糟糕:安全敏感信息!),或者系统调用将检测到越界内存访问并将返回-1,并设置errno为类似"EFAULT"的内容(可能没有发送任何数据)。
由于"message"是一个字符串,应计算其长度,然后只发送该数量的字节(带有或不带有空终止符;这取决于您。接收方可以从数据包的长度重新构建一个空终止字符串。)
该函数不会引发并发问题。
即使多个线程在同一个套接字上调用"sendto"函数,它也是安全的。但如果在流套接字上这样做,您可能会遇到数据以不可预测的方式交错到字节流中的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接