以循环法

时间:2016-02-01 06:29:32

标签: c multithreading pthreads

我正在研究一个多线程服务器应用程序。服务器接受来自多个设备的连接,并为每个连接分配一个线程。线程是一个循环线程,即它使用while循环,迭代直到客户端关闭连接。 / p>

目前,当多个客户端连接到服务器时,只有单个客户端能够进行通信,即单个设备发送的数据在服务器端接收并在数据库中更新,其他设备仍然连接到服务器,但没有从他们。对我来说似乎是什么原因(不确定只是假设)是只有一个线程仍在执行而其他线程没有轮到执行。

所以我想循环安排线程,以便每个线程都执行。如何循环调度线程

我在线获得了以下代码,但无法以循环方式安排线程。

  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
  pthread_attr_setschedpolicy(&attr, SCHED_RR);

这是我创建线程的代码:

connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,(socklen_t*)&clntSock);

 if(connfd > 0){  
     conn_desc = connfd;
     puts("Connection accepted");

if(pthread_create( &thr, &attr ,  connection_handler , (void*)&conn_desc) < 0){    
  perror("could not create thread");
}

1 个答案:

答案 0 :(得分:3)

您的问题 与调度程序策略无关。您的代码中存在潜在的竞争条件。

// parent thread
while (1) {
    listen(...);

    connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,
        (socklen_t*) &clntSock);

    conn_desc = connfd;
    pthread_create(&thr,&attr,connection_handler,(void*) &conn_desc);
}

// child thread function
void *
connection_handler(void *ptr)
{
    int fildes = *(int *) ptr;
    ...
    return (void *) 0;
}

竞争是父级可以在第一个线程能够取消引用ptr之前触发第二个线程。因此,两个线程将使用相同的connfd

为了纠正这个问题,我们需要稍微修改一下调用序列为pass-by-value:

// parent thread
while (1) {
    listen(...);

    connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,
        (socklen_t*) &clntSock);

    pthread_create(&thr,&attr,connection_handler,(void*) connfd);
}

// child thread function
void *
connection_handler(void *ptr)
{
    int fildes = (int) ptr;
    ...
    return (void *) 0;
}

旁注:保证以这种方式在指针内传递int,但对于粘贴者,请参见下文。

// parent thread
while (1) {
    listen(...);

    connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,
        (socklen_t*) &clntSock);

    ptr = malloc(sizeof(int));
    *ptr = connfd;

    pthread_create(&thr,&attr,connection_handler,(void*) ptr);
}

// child thread function
void *
connection_handler(void *ptr)
{
    int fildes = *(int *) ptr;
    free(ptr);
    ...
    return (void *) 0;
}