zoukankan      html  css  js  c++  java
  • 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)

  • 相关阅读:
    数据绑定表达式语法(Eval,Bind区别)
    使用博客园的第一件事 自定义主题
    sql2000 跨服务器复制表数据
    使用UpdatePanel 局部刷新出现中文乱码的解决方法!!
    MMC不能打开文件MSC文件
    sql 日期 、时间相关
    loaded AS2 swf call function in AS3 holder
    Rewrite the master page form action attribute in asp.net 2.0
    100万个不重复的8位的随机数
    flash 中实现斜切变型
  • 原文地址:https://www.cnblogs.com/gd-luojialin/p/9216025.html
Copyright © 2011-2022 走看看