这篇文章上次修改于 1135 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
创建线程
创建变量储存线程 id
pthread_t pth ;//线程id
(可选)线程属性
(可选)可自定义线程属性,也可使用默认 NULL
//自定义线程属性
pthread_attr_t attr;// 初始化线程属性 && creat 也可传 NULL
//初始化线程属性
int pthread_attr_init(pthread_attr_t *attr);
//销毁线程属性所占用的资源
pthread_attr_destroy();
//设置线程属性,分离 or 非分离
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
//获取程属性,分离 or 非分离
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
// detachstate:
// PTHREAD_CREATE_DETACHED(分离线程)
// PTHREAD _CREATE_JOINABLE(非分离线程)
int pthread_attr_getdetachstate(const pthread_attr_t *__attr, int *__detachstate);
//获取线程状态保存到第二个参数
// 判断线程状态
if (detachstate == PTHREAD_CREATE_DETACHED) //判断分离
printf("thread detached\n");
else if (detachstate == PTHREAD_CREATE_JOINABLE)//判断非分离
printf("thread join\n");
else
printf("thread unknown\n");
creat 线程
pthread*create(&pth, NULL, (void *)func, (void \_)argv);
//(指定线程 id,线程属性,执行函数,函数参数)
int pthread_create(pthread_t *__restrict__ __newthread, const pthread_attr_t *__restrict__ __attr, void *(*__start_routine)(void *), void *__restrict__ __arg)
线程其他用法
pthread_exit()//退出线程
pthread_join()//阻塞等待回收线程 ,第二个参数保存返回值
pthread_cancel() //取消线程(到达取消点时取消)
pthread_self();//获取线程id
互斥量使用
初始化互斥量
1. 静态初始化
如果互斥锁 mutex 是静态分配的(定义在全局,或加了 static 关键字修饰),可以直接 使用宏进行初始化。(可移植性差)
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
2. 动态初始化
局部变量应采用动态初始化。
pthread_mutex_init(&lock, NULL)//默认属性(线程间共享)
正常 创建线程
每个线程中
pthread_mutex_lock(&lock);或 pthread_mutex_trylock(&lock);
/*------------ 使用 -------------*/
pthread_mutex_unlock(&lock);
销毁互斥量(仅动态初始化)
pthread_mutex_destroy(&lock);
条件变量 pthread_cond_t
经常结合互斥量使用,且与互斥量使用方式类似
条件变量初始化
静态初始化
pthread_cond_t cond=THREAD_COND_INITIALIZE;
动态初始化
pthread_cond_init();
通知与等待
pthread_cond_signal();//只保证唤醒至少一条遭到阻塞的线程
pthread_cond_broadcast();//会唤醒所有遭阻塞的线程
pthread_cond_wait();//函数将阻塞一线程,直至收到条件变量 cond的通知。
pthread_cond_timedwait();//参数来指定休眠时间的上限。
/*
参数abstime是一个timespec类型的结构(见23.4.2节),用以指定自Epoch(参考10.1节)以来以秒和纳秒(nanosecond)为单位表示的绝对(absolute)时间。如果abstime指定的时间间隔到期且无相关条件变量的通知,则返回ETIMEOUT错误
*/
生产者消费者模型之互斥量
生产者(子线程)
- 加锁
- 判断缓冲区容量
空闲/充足:
生产+操作+通知 - 解锁
消费者(主线程)
一定要先加锁再判断
- 加锁
- 判断
缓冲区空:堵塞 - 操作
- 解锁
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <wait.h>
#include <errno.h>
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char header[10] = {0}; //缓冲区大小10
void *producter(void *argv)
{
//生产者
//1. 加锁
//2. 判断缓冲区容量
// 空闲/充足:
// 生产+操作+通知
//3. 解锁
char temp[30] = {0};
do
{
//满了不生产
pthread_mutex_lock(&mutex);
if (strlen(header) != 9) //判断是否满
{
printf("i am producter%ld\n", pthread_self());
strcpy(temp, "aaa");
strcat(header, temp);
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
memset(temp, 0, sizeof(char) * 30);
sleep(rand() % 3);
} while (1);
}
void *customer(void *argv)
{
//消费者
//1.加锁
//2.判断
// 缓冲区空:堵塞
//3.操作
//4.解锁
do
{
pthread_mutex_lock(&mutex);
while (strlen(header) == 0) //空了不消费
pthread_cond_wait(&cond, &mutex);
printf(" %s\n", header);
header[strlen(header) - 3] = '\0';
pthread_mutex_unlock(&mutex);
printf(" i am customer %ld\n", pthread_self());
sleep(rand() % 3);
} while (1);
}
int main()
{
pthread_t tid[12];
srand(time(NULL));
int i = 0;
for (i = 0; i < 5; i++)
pthread_create(&tid[i], NULL, customer, NULL);
for (i = 0; i < 5; i++)
pthread_create(&tid[i], NULL, producter, NULL);
sleep(100);
}
Posix 无名信号量
可用于线程间也可用于进程间
sem_init 函数参 2:pshared
取0
用于线程
间;
取非 0
(一般为 1)用于进程间
头文件
include<semaphore.h>
变量类型
sem_t
类型
sem_t sem;//规定信号量 sem 不能 < 0
常用函数
sem_init 函数
sem_destroy 函数
sem_wait 函数
sem_post 函数
sem_wait: 1. 信号量大于 0,则信号量--
| 2. 信号量等于 0,造成线程阻塞(类比 pthread_mutex_lock)
|
|
sem_post: 将信号量++,同时唤醒阻塞在信号量上的线程 (类比 pthread_mutex_unlock)
sem_trywait 函数
sem_timedwait 函数
函数介绍
sem_init 函数
int sem_init(sem_t *sem, int pshared, unsigned int value);
参 1:sem 信号量
参 2:pshared 取 0 用于线程间;
取非 0(一般为 1)用于进程间
参 3:value 指定信号量初值
sem_destroy 函数
int sem_destroy(sem_t *sem);
sem_wait 函数
1. 信号量大于 0,则信号量--
2. 信号量等于 0,造成线程阻塞(类比 pthread_mutex_lock)
int sem_wait(sem_t *sem);
sem_post 函数
给信号量解锁 ++
int sem_post(sem_t *sem);
sem_trywait 函数
尝试对信号量加锁 -- (与 sem_wait 的区别类比 lock 和 trylock)
int sem_trywait(sem_t *sem);
sem_timedwait 函数
限时尝试对信号量加锁
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
参 2:abs_timeout 采用的是绝对时间。
定时 1 秒:
time_t cur = time(NULL); 获取当前时间。
struct timespec t; 定义 timespec 结构体变量 t
t.tv_sec = cur+1; 定时 1 秒
t.tv_nsec = t.tv_sec +100;
sem_timedwait(&sem, &t); 传参
生产者消费者模型之信号量
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <wait.h>
#include <errno.h>
#include <pthread.h>
char header[10] = {0}; //缓冲区大小10
sem_t fre;
sem_t used;
void *producter(void *argv)
{
char temp[30] = {0};
do
{
sem_wait(&fre);//fre-- 为负则堵塞
strcpy(temp, "aaa");
strcat(header, temp);
sem_post(&used);//used++
memset(temp, 0, sizeof(char) * 30);
sleep(rand() % 3);
} while (1);
}
void *customer(void *argv)
{
do
{
sem_wait(&used);//used-- 为负堵塞
printf("%s\n", header);
header[strlen(header - 3)] = '\0';
sem_post(&fre);//fre++
sleep(rand() % 3);
} while (1);
}
int main()
{
pthread_t tid[12];
srand(time(NULL));
sem_init(&used, 0, 0);
sem_init(&fre, 0, 3);//最多生产3个数据
int i = 0;
for (i = 0; i < 5; i++)
pthread_create(&tid[i], NULL, customer, NULL);
for (i = 0; i < 5; i++)
pthread_create(&tid[i], NULL, producter, NULL);
sleep(15);
sem_destroy(&used);
sem_destroy(&fre);
}
读写锁
写独占、读共享
读锁、写锁并行阻塞,写锁优先级高
定义一个读写锁变量
pthread_rwlock_t
类型
pthread_rwlock_t rwlock;
主要应用函数
pthread_rwlock_init 函数
pthread_rwlock_destroy 函数
pthread_rwlock_rdlock 函数
pthread_rwlock_wrlock 函数
pthread_rwlock_tryrdlock 函数
pthread_rwlock_trywrlock 函数
pthread_rwlock_unlock 函数
线程池
/* 待完成 */
没有评论