2013-02-10 83 views
0

我试图掌握多线程编程的概念,我觉得我做的很好,但后来我发现下面的代码简单echo服务器:这段代码有竞争条件吗?

http://www.cs.utah.edu/~swalton/listings/sockets/programs/part2/chap7/echo-thread.c

而且我我认为代码是错误的,因为它使用相同的main局部变量来存储每个传入连接的数据套接字。特别是,林关心的main()这一部分:

while (1) 
{ int client, addr_size = sizeof(addr); 
    pthread_t child; 

    client = accept(sd, (struct sockaddr*)&addr, &addr_size); 
    printf("Connected: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 
    if (pthread_create(&child, NULL, Child, &client) != 0) 
     perror("Thread creation"); 
    else 
     pthread_detach(child); /* disassociate from parent */ 
} 

据我了解,变量client,本地的while循环,在完全相同的地址在每次循环分配。因此,当第一个客户端被接受时,线程接收到&client,并且当第二个客户端被接受时,client的值被新的数据套接字覆盖,并且这可能在已经运行的线程中产生副作用第一个客户。

五合一功能Child,这是服务线程的代码,我可以看到参数被复制到一个局部变量:

void* Child(void* arg) 
{ char line[100]; 
    int bytes_read; 
    int client = *(int *)arg; 
    ...etc... 

,可能笔者认为这个副本让他以后篡改主要client变量,但恕我直言,这可能会导致竞争条件。如果第二个客户端在第一个线程复制此变量时到达,则复制的值可能会损坏。

我对不对?

回答

1

是的,你是对的。有两个明显的方式来解决这个问题:

  1. 通行证client到线程,而不是&client

  2. 在堆上分配一个新的整数并将其地址传递给该线程,并让线程在完成时释放它。

+0

除此之外,'accept()'可能会失败。在这种情况下'client'不会被覆盖。 – 2013-11-23 15:38:43

1

是的,你是对的。

你可以证明你是对的int client = *(int*)arg;前添加一个长sleep,并连接到服务器的两倍,而第一个客户端线程。