好记性不如烂笔头
POSIX线程(POSIX threads),简称Pthreads,是线程的POSIX标准。该标准定义了创建和操纵线程的一整套API。在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操作系统的线程。Windows操作系统也有其移植版pthreads-win32
API
一、 Pthreads API中的函数可以非正式的划分为三大类:
- 线程管理(Thread management): 第一类函数直接用于线程:创建(creating),分离(detaching),连接(joining)等等。包含了用于设置和查询线程属性(可连接,调度属性等)的函数。
- 互斥量(Mutexes): 第二类函数是用于线程同步的,称为互斥量(mutexes),是"mutual exclusion"的缩写。
- Mutex函数提供了创建,销毁,锁定和解锁互斥量的功能。同时还包括了一些用于设定或修改互斥量属性的函数。
- 条件变量(Condition variables):第三类函数处理共享一个互斥量的线程间的通信,基于程序员指定的条件。这类函数包括指定的条件变量的创建,销毁,等待和受信(signal)。设置查询条件变量属性的函数也包含其中。
- 命名约定:线程库中的所有标识符都以pthread开头
Routine Prefix | Functional Group |
---|---|
pthread_ | 线程本身和各种相关函数 |
pthread_attr_ | 线程属性对象 |
pthread_mutex_ | 互斥量 |
pthread_mutexattr_ | 互斥量属性对象 |
pthread_cond_ | 条件变量 |
pthread_condattr_ | 条件变量属性对象 |
pthread_key_ | 线程数据键(Thread-specific data keys) |
- 在API的设计中充满了不透明对象的概念,基本调用可以创建或修改不透明对象。不透明的对象可以被一些属性函数调用修改。
例子
一、 创建/终止线程
创建一个文件pthreadTest1
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void* xc(void* arg){
char* c=(char*)arg;
printf("参数%s \n",c);
int i=0;
for (;i<10;i++){
printf("循环%d\n",i);
if(i==5){
pthread_exit(1090000000);
}
}
return 100000222;
}
void main(){
pthread_t tid;
pthread_create(&tid,NULL,xc,"线程!!!!");
void *status;
pthread_join(tid,&status);
printf("返回%d\n",(int)status);
}
编译
gcc pthreadTest1.c -o pthreadTest1 -lpthread
运行
./pthreadTest1
结果:
参数线程!!!!
循环0
循环1
循环2
循环3
循环4
循环5
返回1090000000
二、线程同步
创建一个文件pthreadTest2
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int i = 0;
//互斥锁
pthread_mutex_t mutex;
void* thr_fun(void* arg){
//加锁
pthread_mutex_lock(&mutex);
char* no = (char*)arg;
for(;i < 5; i++){
printf("%s thread, i:%d\n",no,i);
sleep(1);
}
i=0;
//解锁
pthread_mutex_unlock(&mutex);
}
void main(){
pthread_t tid1, tid2;
//初始化互斥锁
pthread_mutex_init(&mutex,NULL);
pthread_create(&tid1,NULL,thr_fun,"No1");
pthread_create(&tid2,NULL,thr_fun,"No2");
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
//销毁互斥锁
pthread_mutex_destroy(&mutex);
}
运行结果
No2 thread, i:0
No2 thread, i:1
No2 thread, i:2
No2 thread, i:3
No2 thread, i:4
No1 thread, i:0
No1 thread, i:1
No1 thread, i:2
No1 thread, i:3
No1 thread, i:4
三、生产消费者线程
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
//消费者数量
#define CONSUMER_NUM 2
//生产者数量
#define PRODUCER_NUM 1
pthread_t pids[CONSUMER_NUM+PRODUCER_NUM];
//产品队列
int ready = 0;
//互斥锁
pthread_mutex_t mutex;
//条件变量
pthread_cond_t has_product;
//生产
void* producer(void* arg){
int no = (int)arg;
//条件变量
for(;;){
pthread_mutex_lock(&mutex);
//往队列中添加产品
ready++;
printf("producer %d, produce product\n",no);
//fflush(NULL);
//通知消费者,有新的产品可以消费了
//会阻塞输出
pthread_cond_signal(&has_product);
printf("producer %d, singal\n",no);
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
//消费者
void* consumer(void* arg){
int num = (int)arg;
for(;;){
pthread_mutex_lock(&mutex);
//while?
//superious wake ‘惊群效应’
while(ready==0){
//没有产品,继续等待
//1.阻塞等待has_product被唤醒
//2.释放互斥锁,pthread_mutex_unlock
//3.被唤醒时,解除阻塞,重新申请获得互斥锁pthread_mutex_lock
printf("%d consumer wait\n",num);
pthread_cond_wait(&has_product,&mutex);
}
//有产品,消费产品
ready--;
printf("%d consume product\n",num);
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
void main(){
//初始化互斥锁和条件变量
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&has_product,NULL);
printf("init\n");
int i;
for(i=0; i<PRODUCER_NUM;i++){
//生产者线程
printf("%d\n",i);
pthread_create(&pids[i],NULL,producer,(void*)i);
}
for(i=0; i<CONSUMER_NUM;i++){
//消费者线程
pthread_create(&pids[PRODUCER_NUM+i],NULL,consumer,(void*)i);
}
//等待
sleep(10);
for(i=0; i<PRODUCER_NUM+CONSUMER_NUM;i++){
pthread_join(pids[i],NULL);
}
//销毁互斥锁和条件变量
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&has_product);
}