多线程程序中的stdio同步

来源:互联网 发布:html class属性 数据库 编辑:程序博客网 时间:2024/05/19 19:32

        在多线程程序中,stdio文件描述符是被各个线程共享的。如果多个线程需要进行stdio操作,那么stdio同步就是一个值得关注的问题了。为了实现stdio线程安全,flockfile和funlockfile调用就显得非常重要了。在很多的情况下,一些stdio操作以不被中断的顺序是非常重要的。        

        下面的程序就是一个多线程调用stdio操作的例子,每个线程都试图使用stdio实现命令行读写,但是输入输出设备是唯一的。我们可以把prompt_routine()中的一次输出操作(printf)和一次读操作(fgets)看做一次事务。根据事务的特性,每次事务都是应该原子性的完成。如果没有flockfile和funlockfile调用,就可能出现如下的状况:一号线程printf调用完成之后被挂起(这是非常有可能的,printf会产生一次系统调用,这很可能会导致一次新的进程调度),然后二号线程占用了CPU,它顺利地执行了一次printf和fgets。这样的效果就是非常混乱的,用户明明在和一号线程交互,却莫名其秒地冲出一个二号线程(大哥,你小三吧!)。

/* * flock.c * * Demonstrate use of stdio file locking to generate an "atomic" * prompting sequence. The write to stdout and the read from * stdin cannot be separated. */#include <pthread.h>#include "errors.h"/* * This routine writes a prompt to stdout (passed as the thread's * "arg"), and reads a response. All other I/O to stdin and stdout * is prevented by the file locks until both prompt and fgets are * complete. */void *prompt_routine (void *arg){    char *prompt = (char*)arg;    char *string;    int len;    string = (char*)malloc (128);    if (string == NULL)        errno_abort ("Alloc string");    flockfile (stdin);    flockfile (stdout);    printf (prompt);    if (fgets (string, 128, stdin) == NULL)        string[0] = '\0';    else {        len = strlen (string);        if (len > 0 && string[len-1] == '\n')            string[len-1] = '\0';    }    funlockfile (stdout);    funlockfile (stdin);    return (void*)string;}int main (int argc, char *argv[]){    pthread_t thread1, thread2, thread3;    char *string;    int status;#ifdef sun    /*     * On Solaris 2.5, threads are not timesliced. To ensure     * that our threads can run concurrently, we need to     * increase the concurrency level.     */    DPRINTF (("Setting concurrency level to 4\n"));    thr_setconcurrency (4);#endif    status = pthread_create (        &thread1, NULL, prompt_routine, "Thread 1> ");    if (status != 0)        err_abort (status, "Create thread");    status = pthread_create (        &thread2, NULL, prompt_routine, "Thread 2> ");    if (status != 0)        err_abort (status, "Create thread");    status = pthread_create (        &thread3, NULL, prompt_routine, "Thread 3> ");    if (status != 0)        err_abort (status, "Create thread");    status = pthread_join (thread1, (void**)&string);    if (status != 0)        err_abort (status, "Join thread");    printf ("Thread 1: \"%s\"\n", string);    free (string);    status = pthread_join (thread2, (void**)&string);    if (status != 0)        err_abort (status, "Join thread");    printf ("Thread 1: \"%s\"\n", string);    free (string);    status = pthread_join (thread3, (void**)&string);    if (status != 0)        err_abort (status, "Join thread");    printf ("Thread 1: \"%s\"\n", string);    free (string);    return 0;}
        问题:为什么各个线程之间不会形成死锁?在第三章中有过明确的说明,多临界资源情况下避免死锁的两种常见方法:
        1.各个线程以固定的顺序对资源加锁
        2.试加锁和退回
        在本例中,各个线程运行的代码都是prompt_routine(),相当于使用了第一种方法,所以不会形成死锁。

0 0
原创粉丝点击