24多线程

Posted gd-luojialin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 [email protected] -lpthread

clean:

      rm -fr $(BIN) $(CPPBIN)

 

以上是关于24多线程的主要内容,如果未能解决你的问题,请参考以下文章

java 多线程 24 : 线程组

2014.2.24 带参数多线程实例

《狂神说——多线程》

题目24-多线程两种实现方式

1.1 Java多线程原理

java基础--24.多线程的应用--电影院卖票程序的实现