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多线程的主要内容,如果未能解决你的问题,请参考以下文章