27
2017
09

Linux下pthread

方法介绍

数据类型:

pthread_t:线程ID
pthread_attr_t:线程属性

操纵函数:

pthread_create():创建一个线程
pthread_exit():终止当前线程
pthread_cancel():中断另外一个线程的运行
pthread_join():阻塞当前的线程,直到另外一个线程运行结束
pthread_attr_init():初始化线程的属性
pthread_attr_setdetachstate():设置脱离状态的属性(决定这个线程在终止时是否可以被结合)
pthread_attr_getdetachstate():获取脱离状态的属性
pthread_attr_destroy():删除线程的属性
pthread_kill():向线程发送一个信号

同步函数:

用于 mutex 和条件变量
pthread_mutex_init() 初始化互斥锁
pthread_mutex_destroy() 删除互斥锁
pthread_mutex_lock():占有互斥锁(阻塞操作)
pthread_mutex_trylock():试图占有互斥锁(不阻塞操作)。即,当互斥锁空闲时,将占有该锁;否则,立即返回。
pthread_mutex_unlock(): 释放互斥锁
pthread_cond_init():初始化条件变量
pthread_cond_destroy():销毁条件变量
pthread_cond_signal(): 唤醒第一个调用pthread_cond_wait()而进入睡眠的线程
pthread_cond_wait(): 等待条件变量的特殊条件发生
Thread-local storage(或者以Pthreads术语,称作线程特有数据):
pthread_key_create(): 分配用于标识进程中线程特定数据的键
pthread_setspecific(): 为指定线程特定数据键设置线程特定绑定
pthread_getspecific(): 获取调用线程的键绑定,并将该绑定存储在 value 指向的位置中
pthread_key_delete(): 销毁现有线程特定数据键
pthread_attr_getschedparam();获取线程优先级
pthread_attr_setschedparam();设置线程优先级

工具函数:

pthread_equal(): 对两个线程的线程标识号进行比较
pthread_detach(): 分离线程
pthread_self(): 查询线程自身线程标识号 

1、创建一个线程

这里写图片描述

这里的pthread_create(&tid,NULL,thr_fun,”1”); 就是创建一个id为tid的线程

之后编译生成一个可执行文件

gcc 01.c -o 01 -lpthread

这里写图片描述

之后执行这个可执行文件

这里写图片描述

发现他只打印了第一句话,这个时候不是子线程没执行,而是因为主线程没有等待子线程就已经结束了,程序都干掉了,线程还会存在吗,这个时候在里面睡眠以下就好了

这里写图片描述

再来执行一下

这里写图片描述

现在就好了

2、阻塞线程:pthread_join

刚才是因为睡眠了一秒,才执行了子线程,现在可以让他等待子线程结束了再往下走

这里写图片描述

执行

这里写图片描述

可以看到最后一行拿到了返回值1,这个时候我在中间把线程杀死

这里写图片描述

执行一下
这里写图片描述

会发现最后的返回值变成了pthread_exit中传入的参数

3、互斥锁

这里写图片描述

执行一下

这里写图片描述

会看到他是乱的,那怎么有顺序的执行呢

#include <stdlib.h>                                                                                                                                                
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

int i = 0;
//互斥锁
pthread_mutex_t mutex;

void* thr_fun(void* arg){
    char* no = (char*)arg;
    //加锁
    pthread_mutex_lock(&mutex);
    for (; i < 5; i++){
        printf("线程名:%s,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);
}

执行的结果是

这里写图片描述

总结:

pthread_mutex_t:互斥锁
pthread_mutex_lock(&mutex):加锁
pthread_mutex_unlock(&mutex):解锁
pthread_mutex_init(&mutex,NULL):初始化互斥锁
pthread_mutex_destroy(&mutex):销毁互斥锁

加锁之后就表示别的线程不能访问,只有解锁之后才能交给别的线程访问

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);

}

执行之后的结果

[root@iz2zefc73lz5afpo72um1nz thread]# ./003
init
0
1 consumer wait
producer 0,produce product
producer 0 ,singal
0 consume product
1 consumer wait
0 consumer wait
producer 0,produce product
producer 0 ,singal
1 consume product
producer 0,produce product
producer 0 ,singal
1 consume product
0 consumer wait
producer 0,produce product
producer 0 ,singal
1 consume product
0 consumer wait
producer 0,produce product
producer 0 ,singal
1 consume product
0 consumer wait

5、ubuntu上安装pthread手册

在ubuntu上安装pthread手册

apt-get install manpages-posix-dev

查看的时候使用

查看有哪些函数:man -k pthread
查看函数详细内容,比如查看pthread_create:man pthread_create
按q退出
上一篇:Android 布局优化-ViewStub 视图 下一篇:Android O 新特性