这段代码中存在竞争条件?

时间:2013-02-10 22:09:31

标签: c multithreading thread-safety race-condition

我正在尝试掌握多线程编程的概念,我认为我做得很好,但后来我找到了一个简单的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变量,但恕我直言,这可能会导致竞争条件。如果第二个客户端在第一个线程复制此变量时到达,则复制的值可能已损坏。

我是对的吗?

2 个答案:

答案 0 :(得分:1)

是的,你是对的。有两种明显的方法可以解决这个问题:

  1. client传递给主题,而不是&client

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

答案 1 :(得分:1)

是的,你是对的。

您可以通过在sleep之前添加一个长int client = *(int*)arg;并在第一个客户端线程连接到服务器两次来证明您是对的。