zoukankan      html  css  js  c++  java
  • pthread基本操作

    • 进程的创建(pthread_create)


    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg)

    RETURN VALUE

    On success, pthread_create() returns 0; on error, it returns an error number.
    函数参数:
      1. pthread_t *thread, 传入创建的pthread_t指针。
      2.const pthread_attr_t *attr,修改进程的属性,如果不设置则可以传入NULL
      3.void *(*start_routine) (void *)创建出来的进程执行的函数,返回类型为void*,并且需要带参数void*
      4. void *arg 传入的函数参数。

    在给函数传参数的时候,如果只是单纯的传入数字,我们可以采用(大致的写几行伪代码):

    void* fun(void *arg){
    int i = (argumentType)arg;
    }
    main(){
    int i;
    pthread_t pid;
    pthread_create(&pid,NULL,fun,(void*)i);}

    如果是在32位操作系统,此代码中的argumentType应该写为int,因为void*指针的大小也是4位。

    如果是在64位操作系统,此代码中的argumentType应该写为long,因为void*指针的大小是8位,如果使用int会报错而不通过编译。

    这里采用int转void*,而不是int* 转 void*的原因是,如果实在多线程的创建过程中,传递的是地址,其他线程如果修改这个数据,在本线程的后续操作中会使数据改变而导致达不到自己想要的效果。

    当我们需要传递多个参数的时候,便可以采用结构体,定义一个结构体数据,然后通过指针传递给函数,接着转换一下类型就好了。

    • pthread_join, pthread_detach
    typedef struct retval{
        int id;
        char str[10];
    }*pretval;
    void *fun1(void *arg){
        pretval argtemp = (pretval)arg;
        argtemp->id = 123123;
        printf("%d,%s
    ",argtemp->id,argtemp->str);
        pthread_exit(argtemp);
    }
    int main()
    {
        pthread_t pthread1;
        retval* arg = new retval;
        arg->id = 10;
        strcpy(arg->str,"hello123");
        int rect = pthread_create(&pthread1,NULL,fun1,(void*)arg);
        pthread_join(pthread1,(void **)&arg);
        printf("this is main %d %s
    ",arg->id,arg->str);
    }

    pthread_join用来回收线程,需要指定回收线程的ID和线程的返回参数(可选),这个例子是使用结构提体参,在线程函数中改变结构体变量的值,然后传递给pthread_join,接着显示修改后的值。这样基本上就了解了pthread_join的用法,另外pthread_join是阻塞函数。

    如果不回收死亡的线程,便会产生僵尸线程。

    pthread_detach使用来分离线程,如果我们使用了pthread_detach,那么这个进程在执行完自己的任务之后便会自动死亡并回收。

    但是如果使用了detach之后,再使用join,join的返回值将会是错误的number,好像是22。

    如果我们使用很多的线程,使用pthread_detach是有一点不太方便,这个时候我们便可以使用上面pthread_create函数的第二个参数来设置创建进程的属性。

    #include <pthread.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    void *fun(void *){
        printf("hello
    ");
        //pthread_cond_timedwait();
        exit(1);
        return NULL;
    }
    int main()
    {
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
        pthread_t pid;
        pthread_create(&pid,&attr,fun,NULL);
        sleep(20);
        return 0;
    }

    需要注意的是需要初始化之后赋值才能使用,不然有可能会达不到你的期望。

    • pthread_cancel

     pthread_cancel,是计算机语言,它发送终止信号给thread线程,如果成功则返回0,否则为非0值。

    • 有关线程的退出问题

    接下来我们聊聊exit,_exit,return,pthread_exit.

    _exit():会结束整个进程,不论缓冲区是否有数据。

    exit():会结束整个进程,缓冲区有数据就写到指定的文件描述符。

    return:只是单纯的返回到函数到用的地方,但是当main函数使用的时候,就会退出整个进程,所以要使用pthread_exit.如果是其他线程,则只会退出自己。

    pthread_exit:只会退出单个线程,不影响其他线程。

  • 相关阅读:
    cf605 div3
    how to find Longest Increasing Subsequence Size
    luogu1641 [SDOI2010]生成字符串
    luogu1441 砝码称重
    luogu4218 [JSOI2008] 最小生成树计数
    luogu1514 引水入城
    luogu1312 Mayan游戏 剪枝
    luogu1081 开车旅行 树上倍增
    luogu1052 过河
    luogu1026 统计单词个数
  • 原文地址:https://www.cnblogs.com/jianmoxiansheng-Guo/p/13228887.html
Copyright © 2011-2022 走看看