• 24多线程


    基本概念

    线程:进程中的某一个处理流程

    一个进程可以有多个线程,进程是线程的父进程

    所有线程与父进程共享资源

    线程分类

    内核态线程

    由内核调度程序直接调度,充分发挥多处理器的优势

    目前linux系统标准线程库采用内核线程方式实现多线程

    用户态线程

    一个进程包含多个线程,这些线程从内核调度角度来看只是一个进程,内核把它当一个进程来调度。线程之间调度在用户态进行

    用户态线程优点是调度效率高(不需要内核参与调度),缺点是对于多核处理器利用率不高,一个线程阻塞会导致整个线程组阻塞

    创建线程

    #include<pthread.h>

    int  pthread_create(pthread_t *id,  pthread_attr_t  *attr,  void *pFun,  void *args)

    参数:

    id :      返回线程ID

    attr:     线程属性

    pFun:  线程调用的函数

    args: 线程函数的参数

    注意:创建成功返回0,否则返回错误码

    线程管理

    pthread_exit(void *pRet)             pRet指定线程退出返回值

    int  pthread_join(pthread_t  id,  void **pRet)

    使主进程等待线程完成后才退出

    pRet 获得 pthread_exit 函数调用的返回值,一般为NULL

    pthread_self()

    线程函数里,获取本线程的线程ID

    pthread_getattr_np(pthread_t id, pthread_attr_t *attr)

    获取线程属性

    线程属性, 调用 init 函数初始化线程属性

    pthread_attr_init(pthread_attr_t  *attr)

    struct pthread_attr_t {

        int         __detachstate;  

        int         __schedpolicy;

        struct sched_param  __schedparam;

        int          __inheritsched;

        int            __scope;

        size_t    __guardsize;

        int          __stackaddr_set;

        void *    __stackaddr;

        unsigned long int  __stacksize;

    }

    线程属性详解

    __detachstate: 线程分离状态

    PTHREAD_CREATE_JOINABLE      可与其他线程连接

    PTHREAD_CREATE_DETACHED

    设置/获取线程分离状态

    int  pthread_attr_setdetachstate(pthread_attr_t *attr,  int  detachstate)

    int  pthread_attr_getdetachstate(pthread_attr_t *attr,  int *pdetachstate)

    __schedpolicy:    线程调度策略

    SCHED_OTHER       系统默认(分时调度),各个优先级任务时间轮换

    SCHED_FIFO            实时调度,先到先服务(独占)

    SCHED_RR               实时调度,时间片轮转(高优先级轮换)

    设置/获取线程调度策略

    int pthread_attr_setschedpolicy(pthread_attr_t *attr,  int  policy)

    int pthread_attr_getschedpolicy (pthread_attr_t *attr,  int *pPolicy)

    __schedparam 线程优先级信息

    __schedparam.sched_priority

    设置获取线程属性参数

    int pthread_attr_setschedparam(pthread_attr_t *attr, struct sched_param  *param)

    int pthread_attr_getschedparam(pthread_attr_t *attr, struct sched_param  *param)

    对于 SCHED_FIFO    SCHED_RR 调度,设置优先级param.sched_priority

    __inheritsched   线程继承性

    PTHREAD_INHERIT_SCHED     从父进程继承调度属性

    PTHREAD_EXPLICIT_SCHED   不从父进程继承调度属性

    设置/获取线程继承性

    int pthread_attr_setinheritsched(pthread_attr_t *attr,  int  inheritsched)

    int pthread_attr_getinheritsched(pthread_attr_t *attr,  int  *pinheritsched)

    __scope      线程作用域

    PTHREAD_SCOPE_SYSTEM     系统所有进程间调度

    PTHREAD_SCOPE_PROCESS  当前进程间调度

    设置/获取线程作用域

    int pthread_attr_setscope(pthread_attr_t *attr,  int scope)

    int pthread_attr_getscope(pthread_attr_t *attr,  int *pscope)

    __stackaddr   线程堆栈地址

    __stacksize    线程堆栈大小

    获取/设置线程桟

    int pthread_attr_setstackaddr(pthread_attr_t *attr,  void * stackaddr)

    int pthread_attr_getstackaddr(pthread_attr_t *attr,  void ** stackaddr)

    int pthread_attr_setstacksize(pthread_attr_t *attr,  size_t  *stacksize)

    int pthread_attr_setstacksize(pthread_attr_t *attr,  size_t  *stacksize)

    __guardsize   警戒缓冲区大小

    线程桟末尾防止桟溢出的扩展内存大小

    设置/获取线程警戒缓冲区

    int pthread_attr_getguardsize(pthread_attr_t *attr, size_t  *guardsize)

    int pthread_attr_setguardsize(pthread_attr_t *attr, size_t  *guardsize)

    无效化线程属性

    pthread_attr_destroy(pthread_attr_t *attr)

    无效化后, 使用attr 创建线程会失败

    退出线程方式

    1:  线程指定函数执行完毕

    2:  进程退出

    3:  线程调用exec函数

    4:  线程调用 pthread_exit 函数退出

    5:  线程调用 pthread_cancel 终止

    pthread_exit(void *pRet)    pRet指定线程退出返回值,可用于pthread_join()

    例子:

    #define _GNU_SOURCE

    #include<stdio.h>

    #include<pthread.h>

    #include<stdlib.h>

    #include<unistd.h>

    #include<string.h>

    int g_ret;

    void* thread()

    {

          printf("My thread id %#x ", (int)pthread_self());

          int i = 10;

          while(i--)

          {

               printf("-> %d ", i);

               usleep(1000);

          }

          g_ret = 100;

          pthread_exit(&g_ret);

          return NULL;

    }

    int create_demo()

    {

          pthread_t tid;

          int iRet;

          iRet = pthread_create(&tid, NULL, thread, NULL);

          if (iRet)

          {

               perror("Fail to pthread_create!");

               return iRet;

          }

          printf("Create thread: %#x ",(int)tid);

          int i=5;

          while(i--)

          {

               printf("Main -> %d ", i);

               usleep(1000);

          }

         

          //pthread_join(tid, NULL);

          int *p;

          pthread_join(tid, (void*)&p);//p point to  g_ret;

          printf("Exit code %d ", *p);

          //sleep(1);

          return 0;

    }

    void* threadn(void* param)

    {

          int n = *((int*)param);

         

          int iRet=0;

          int i;

          for (i=0; i<n; i++)

          {

               iRet+=i;

               fprintf(stderr, "thread[%d]->%d ", n, iRet);

               usleep(100*1000);

          }

          printf(" ");

          return NULL;

    }

    void Test_threadn()

    {

          pthread_t tid1, tid2, tid3;

          int x1=20, x2=15, x3=10;

          pthread_create(&tid1, NULL, threadn, (void*)&x1);

          pthread_create(&tid2, NULL, threadn, (void*)&x2);

          pthread_create(&tid3, NULL, threadn, (void*)&x3);

         

          pthread_join(tid1, NULL);

          pthread_join(tid2, NULL);

          pthread_join(tid3, NULL);

          return;

    }

    typedef struct tagNumArr

    {

          int *arr;

          int size;

    }N_ARR;

    void* largeSort(void *param)

    {

          N_ARR stArr;

         

          memcpy(&stArr, param, sizeof(N_ARR));

          /* sort(stArr.arr, stArr.size) */

         

          /* Save(stArr) */

          return NULL;

    }

    void Test_LargeSort()

    {

          int arr[] = {1,3,5,7,9,2,4,6,8,10};

          N_ARR  stArr = {arr, sizeof(arr)/sizeof(arr[0])};

          pthread_t tid;

          pthread_create(&tid, NULL, largeSort, (void*)&stArr);

          //.......

          pthread_join(tid, NULL);

          return;

    }

    void Print_SelfAttr()

    {

          pthread_attr_t attr;

          pthread_t tid = pthread_self();

          pthread_getattr_np(tid, &attr);

          int iDetachState;

          pthread_attr_getdetachstate(&attr, &iDetachState);

          printf("Detach: %s ", iDetachState == PTHREAD_CREATE_DETACHED?"Detached":"Joinable");

          return;

    }

    void Test_ThreadAttr()

    {

          pthread_attr_t attr;

          pthread_attr_init(&attr);//initialized thread attrib

          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

         

          pthread_t tid;

          pthread_create(&tid, &attr, (void*)Print_SelfAttr, NULL);

          pthread_attr_destroy(&attr);

          pthread_join(tid, NULL);

          return; 

    }

    int main()

    {

          create_demo();

          //Test_threadn();

          //Test_ThreadAttr();

          return 0;

    }

    注意:

    使用gcc –g –Wall main.c –o main 将会出错。

    undefined reference to `pthread_create'

    undefined reference to `pthread_join'

    collect2: error: ld returned 1 exit status

    但是使用gcc –g –Wall  -c main.c -o main.o 不会出错。

    说明编译过程没问题,而在链接过程出问题。

    因此

    gcc –g –Wall main.c –o main –lpthread

    -l 代表链接到pthread库

    Makefile修改:

    .PHONY:clean all

    SRC=$(wildcard *.c)

    BIN=$(SRC:%.c=%)

    CPPSRC=$(wildcard *.cpp)

    CPPBIN=$(CPPSRC:%.cpp=%)

    CC=gcc

    CXX=g++

    CFLAGS=-g -Wall

    CXXFLAGS =-g -Wall -std=c++11

    all:$(BIN)  $(CPPBIN)

    $(BIN):%:%.c

          $(CC) $(CFLAGS) $^ -o $@ -lpthread

    clean:

          rm -fr $(BIN) $(CPPBIN)

  • 相关阅读:
    正则表达式
    跨域请求/SpringMVC拦截器
    批量导出
    什么是2MSL以及TIME_WAIT的作用
    使用jstack精确找到异常代码的
    nettry 入站事件如何传递到下一个handler
    netty 引用计数器 ,垃圾回收
    elasticsearch 查询优化
    Spark性能优化指南-高级篇(spark shuffle)
    Broadcast与map进行join,避免shuffle,从而优化spark
  • 原文地址:https://www.cnblogs.com/gd-luojialin/p/9216025.html
Copyright © 2020-2023  润新知