使用条件变量和互斥锁实现线程同步
条件变量(cond)使在多线程程序中用来实现“等待--->唤醒”逻辑常用的方法,是进程间同步的一种机制。条件变量用来阻塞一个线程,直到条件满足被触发为止,通常情况下条件变量和互斥量同时使用。一般条件变量有两个状态:(1)一个/多个线程为等待“条件变量的条件成立“而挂起;(2)另一个线程在“条件变量条件成立时”通知其他线程。
互斥锁的作用:
1. 保护共享数据。 再并发机制的情况下,有时候会有多个线程同时访问同一片数据,为了保护数据操作的原子性就使用互斥锁来保证数据操作的准确性。
2. 保持操作的互斥性。可能一个程序会有多个操作,但是同一个时间只能有一个操作被执行。
为什么条件变量总是和互斥锁结合使用?
1. 互斥锁可以表示的状态太少,所以经常需要条件变量来增加有限的状态
2. 条件变量只是条件,还需要互斥量的保护, 线程改变条件状态之前先要锁住互斥量。
3. 线程之间交换互斥锁的控制权,会带来不必要的时间消耗,加上条件变量就弥补这个弱点
互斥锁的基本函数:
#include <pthread.h>
// 创建一个互斥锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
// 销毁一个互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
// 给一个互斥锁上锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
// 给一个互斥锁上锁但是不会阻塞
int pthread_mutex_trylock(pthread_mutex_t *mutex);
// 给一个互斥锁开锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
条件变量的基本函数:
#include <pthread.h>
// 初始化一个条件变量
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
// 销毁一个条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
// 等待一个条件变量
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
// 带时间限制的条件变量
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
条件变量和互斥锁的变量类型定义: pthread_mutex_t和pthread_cond_t类型
typedef union typedef union
{ {
struct __pthread_mutex_s __data; struct __pthread_cond_s __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T]; char __size[__SIZEOF_PTHREAD_COND_T];
long int __align; __extension__ long long int __align;
} pthread_mutex_t; } pthread_cond_t;
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <time.h>
#include <string.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <time.h>
#include <pthread.h>
#include "my_print.h"
#define MAXLINE 4096
#define err_quit(s) (perror(s), exit(EXIT_FAILURE))
int x = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *wait_ture(void *argv);
void *do_ture(void *argv);
int main(int argc, char **argv)
{
pthread_t threadid[2];
// 创建互斥锁和条件变量
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_create(&threadid[0], NULL, wait_ture, NULL);
sleep(2);
pthread_create(&threadid[1], NULL, do_ture, NULL);
pthread_join(threadid[0], NULL);
pthread_join(threadid[1], NULL);
pthread_cond_destroy(&cond);
return 0;
}
void *wait_ture(void *argv)
{
int ret;
// 上锁,别的线程会被阻塞,执行到等待条件变量的时候线程被挂起,这个互斥锁就会被解锁了
printr("befor mutex\n");
ret = pthread_mutex_lock(&mutex);
printr("after mutex\n");
if (ret < 0)
err_quit("lock error");
// 线程挂起,互斥锁会被解锁
if (pthread_cond_wait(&cond, &mutex) == 0)
printr("wait success! x = %d.\n", x);
pthread_mutex_unlock(&mutex);
return NULL;
}
void *do_ture(void *argv)
{
int ret;
// 获取互斥锁,前面函数等待这里的条件变量就会挂起,这里就会获得互斥锁
ret = pthread_mutex_lock(&mutex);
while (x != 4)
{
if (ret < 0)
err_quit("mutex error");
else if (ret == 0)
{
x++;
printf("done for true, x = %d\n", x);
sleep(1);
}
}
pthread_mutex_unlock(&mutex);
ret = pthread_cond_signal(&cond);
if (ret != 0)
printf("unlock mutex error");
return NULL;
}