处理两个线程,一个休眠,一个等待输入

时间:2018-05-14 03:59:21

标签: c multithreading pthreads

问题:要创建一个接受用户输入但在几秒钟后超时的程序(现在说它是2秒)。

方法:我创建了两个线程,一个用于等待用户输入(inputThreadtid[0]),另一个用于休眠2秒(sleepThread with tid[1])。我从另一个线程的例程中取消一个线程,如下所示:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

pthread_t tid[2];

void* inputThread()
{   
    int n;
    printf("Enter number:");

    // wait for input; if input is given then go ahead and cancel the sleeper thread.
    scanf("%d",&n); 

    // cancel the sleeper thread
    pthread_cancel(tid[1]); 

    printf("Got value:%d\n",n);
}

void* sleepThread()
{
    // sleep for 2 seconds and cancel the input thread.
    sleep(2); 

    // cancel the input thread
    pthread_cancel(tid[0]); 

    printf("\nNo value entered!\n");
}

int main(int argc, char const *argv[])
{
    int r1,r2,r3,r4;

    // input taking thread 
    r1 = pthread_create(&tid[0],NULL,inputThread,NULL); 

    // sleeping thread
    r2 = pthread_create(&tid[1],NULL,sleepThread,NULL);

    r3 = pthread_join(tid[0],NULL);
    r4 = pthread_join(tid[1],NULL);

    return 0;
}

截至目前,该计划按预期运作。

但我的朋友说,保证无法正常工作,因为取决于线程的安排方式。他试着向我解释同样的事情,但我无法理解。他还说pthread_cancel只是取消线程的请求,可能不会成功。

所以有人可以指出潜在的错误和最佳做法,以避免相同。为了保证计划的正常运行,我们也不胜感激。

3 个答案:

答案 0 :(得分:3)

您的朋友关于pthread_cancel是取消线程的请求的部分是正确的,并且可能永远不会成功。

关于日程安排的部分,您需要提供他所拥有的参数。

要解决您的问题,您可以放弃一起使用线程(除非这是您的分配要求),并将selectread一起使用。

这将使解决方案不可移植(仅符合POSIX),但pthreads无论如何也不可移植。

select允许您等待文件描述符(在本例中为0),以便数据可用于读取。它还允许您设置超时。

fd_set set;
FD_ZERO(&set);
FD_SET(0, &set);

struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;

int ret = select(1, &set, NULL, NULL, &timeout);

if (ret == 1) {
    char buffer[20];
    int n;
    read(0, buffer, 20);
    sscanf(buffer, "%d", &n);
    printf("Got value:%d\n",n);
} else {
    printf("Time out\n");
}

答案 1 :(得分:1)

你的朋友是对的,我认为他的意思是你不能假设知道哪个线程先运行/完成。 但是在2秒内肯定会安排两个线程,所以thread1有时间要求用户输入并等待一点输入。

我没有看到大问题,如果没问题,那就不要太担心。

然而,您可以使用SIGALRM信号而不是sleep,但它涉及掩码,需要花费更多时间来理解(我正在做this project:检查task2函数并掩盖它如果你想要一个例子,请使用。)

答案 2 :(得分:0)

pthread_cancel函数调用线程上的线程取消处理程序,然后,一旦它们返回,将调用线程的析构函数,这反过来将终止线程。

因为它是一个请求,它可能会失败,由pthread_cancel指示返回一个非零整数。

如果您使用两个以上的线程来执行此操作,或者更多线程在同一进程中访问stdin,则可能会让线程等待访问stdin,从而导致所需的行为被延迟。