多线程程序中的stdio同步

        在多线程程序中,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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值