线程互斥锁
线程互斥锁也是 信号量 ,只不过线程互斥锁,存在于进程地址空间,用于线程间同步和互斥操作,线程互斥锁它的效率相对信号量来说要高。
线程互斥锁:使用 pthread_mutex_t 的类型来描述一个锁。
这里用到POSIX(可移植操作系统接口)
安装线程 POSIX 帮助手册: sudo apt-get install manpages-posix-dev // 安装posix 帮助手册
初始化线程互斥锁
NAME
pthread_mutex_init — destroy and initialize a mutex
SYNOPSIS
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const
pthread_mutexattr_t *restrict attr);
/*
@描述:
线程互斥锁的PV 操作
P 操作(上锁操作)
初始一个线程互斥锁
@mutex:
需要初始化的线程互斥锁地址
pthread_mutex_t mutex; // 创建了一个互斥锁
&mutex ---> 互斥锁地址
@attr:
线程互斥锁的属性,一般为NULL,采用默认属性
如:
线程的互斥锁默认设置 1 unlock
@return:
成功返回0,失败返回-1
*/
线程互斥锁的PV 操作
P 操作(上锁操作)
int pthread_mutex_lock(pthread_mutex_t *mutex);
/*
作用:
死等上锁,如果该锁没有被释放,则会一直阻塞在此函数,等待该锁被释放。
@mutex:
需要上锁的互斥锁指针
@return:
成功返回0,表示获取到了该互斥锁
返回-1,表示获取出错,没有获取到互斥锁
*/
int pthread_mutex_trylock(pthread_mutex_t *mutex);
/*
作用:
尝试上锁,尝试性上锁,如果该锁没被释放,那么立即返回执行后面的代码。
@mutex:
需要上锁的互斥锁指针
@return:
成功返回0,表示获取到了该互斥锁
其他值,表示没有获取到互斥锁
*/
int pthread_mutex_timedlock(pthread_mutex_t *mutex,struct timespec
*abs_timeout);
/*
作用:
限时上锁,如果该锁没有被释放,则会一直阻塞在此函数中一段实际,等待该锁被释放。如果时间
过了还没有被释放,那么果断放弃执行后面的代码。
@mutex:
需要上锁的互斥锁指针
@abs_timeout:
绝对时间(超时时间),上锁的时间范围。
@return:
成功返回0,表示获取到了该互斥锁
V 操作(解锁操作)
int pthread_mutex_unlock(pthread_mutex_t *mutex);
/*
作用:
解锁线程互斥锁
@mutex:
需要解锁的线程互斥锁指针
*/
线程互斥锁的销毁操作
int pthread_mutex_destroy(pthread_mutex_t *mutex);
/*
作用:
销毁一个线程互斥锁
@mutex:
需要销毁的线程互斥锁指针
@return:
成功返回0,失败返回-1
*/
线程条件变量
线程条件变量:在多线程程序设计中,可以用 条件变量 为表示一个特定的条件或者是事件
pthread_cond_t :来描述一个条件变量(类型)
至于条件变量,到底是一个什么事件或者说表示一个什么条件?完全由程序猿去解释这个条件变量所代表的含义。
在条件变量上的三种操作:
初始化
等待一个条件变量(等待该条件变量所表示的事件)
唤醒一个线程/触发条件变量(唤醒了正在等待该事件的线程)
举个栗子
int data = 0;
main : 主线程:生产者:包工头
data = 1;
t1:子线程:消费者:牛马
when data == 1;
干活
data = 0;
线程条件变量API
初始化/销毁条件变量
NAME
pthread_cond_destroy, pthread_cond_init — destroy and initialize
condition variables
SYNOPSIS
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
等待一个条件变量
/*
@描述:
销毁一个条件变量
@cond:
需要销毁条件变量指针
*/
int pthread_cond_init(pthread_cond_t *restrict cond,const
pthread_condattr_t *restrict attr);
/*
@描述:
初始化一个条件变量
@cond:
需要初始化的条件变量的指针
@attr:
初始化的条件变量的属性,一般为NULL,采用默认设置
@return:
成功返回0,失败返回其他值
*/
等待一个条件变量
NAME
pthread_cond_timedwait, pthread_cond_wait — wait on a condition
SYNOPSIS
#include <pthread.h>
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t
*restrict mutex,
const struct timespec *restrict abstime);
/*
@描述:
限时等待条件变量
@cond:
需要等待的那个条件变量指针
@mutex:
线程互斥锁:为了保护cond所表示的那个事件/共享资源的。
条件变量实际也是一个共享资源。
@abstime:
绝对时间,需要被唤醒的绝对时间
*/
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t
*restrict mutex);
/*
唤醒线程/触发条件变量
@描述:
等待那个条件变量
@cond:
需要等待的那个条件变量指针
@mutex:
线程互斥锁:为了保护cond所表示的那个事件/共享资源的。
条件变量实际也是一个共享资源。
pthread_cond_wait()
{
mutex:locked 上锁
... 准备工作
mutex:unlock 解锁
让出CPU 等待
...
when 当条件产生的时候,其他的线程唤醒我的时候
mutex:locked 上锁
}
@return:
成功返回0,被其他线程唤醒
失败返回其他值
*/
唤醒线程/触发条件变量
NAME
pthread_cond_broadcast, pthread_cond_signal — broadcast or signal a
condition
SYNOPSIS
#include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cond);
/*
@描述:
唤醒所有正在等待的线程
@cond:
那个条件变量
@return:
成功返回0,失败返回其他值
*/
int pthread_cond_signal(pthread_cond_t *cond);
/*
@描述:
只唤醒一个线程在等待的线程。
@cond:
那个条件变量
@return:
成功返回0,失败返回其他值
*/
代码示例(可运行)
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
using std::vector;
// 线程互斥锁
pthread_mutex_t mutex;
// 条件变量
pthread_cond_t cond;
// 公共资源
FILE *file=NULL;
std::string str;
// 消费者,这是个线程函数。
void *NiuMa(void *data)
{
while(1)
{
pthread_mutex_lock(&mutex);
// 等待条件变量:任务
pthread_cond_wait(&cond,&mutex); // 休眠,让出了CPU。这里有个机制,不会让子线程一直占据锁。
if(str == "退出")
{
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
std::cout << fwrite(str.c_str(),str.size(),1,file) << std::endl;
std::cout << pthread_self() << "线程:成功写入内容:<" << str << "> "<< std::endl;
pthread_mutex_unlock(&mutex);
}
}
// 主线程:生产者
int main()
{
// 初始化
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
// 打开文件
file = fopen("./1.txt","w+");
vector<pthread_t> tids(10);
// 创建10个线程
for(int i = 0;i < 10;i++)
{
pthread_create(&tids[i],NULL,NiuMa,NULL);
}
// 通过输入来发布任务
while(1)
{
sleep(4);
pthread_mutex_lock(&mutex);
std::cout << "请输入内容:" ;
std::cin >> str;
pthread_mutex_unlock(&mutex);
if(str == "退出")
{
pthread_cond_broadcast(&cond);
break;
}
//唤醒线程
pthread_cond_signal(&cond);
break;
}
for(int i = 0;i < 10;i++)
{
pthread_join(tids[i],NULL);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
fclose(file);
return 0;
}