线程同步的概念:
多个线程共享相同的内存时,需要看到一致的数据即保证不能读取脏数据,因此需要用到线程同步的知识。
线程同步有哪些方式
1.信号量
2.互斥量
3.条件变量
1. 信号量
信号量是一种特殊类型的变量,它可以被增加或者减少,但对其的关键访问被保证是原子操作,即使在一个多线程程序也是如此。信号量的值代表着资源数的多少,我们先讨论二进制信号量(只有0和1取值),类似于互斥锁。
头文件:< semaphore.h>
信号量创建函数:
int sem_init(sem_t *sem,int pshared,unsigned int value);
参数含义:
sem为要初始化的信号对象
pshared参数控制信号量的类型,如果值为0,就表示这个信号量是当前进程信号的局部信号量,否则,这个信号量就可以在多个进程之间共享。我们只分析当前进程的信号量。
控制信号量值的函数:
int sem_post(sem_t *sem) //相当于V操作
int sem_wait(sem_t *sem) //相当于P操作
另外一个函数:
int sem_trywait(sem_t *sem)//尝试p操作,如果可以申请到资源就成功申请,否则返回一个出错码。
最后一个函数:
int sem_destroy(sem_t *sem)//清理该信号量拥有的资源,如果被清理的资源正被线程等待 就会收到一个错误。
2. 互斥量
它允许程序锁住某个对象,使得每次线程只能有一个线程访问它。为控制对关键代码的访问,必须在进入代码段之前锁住一个互斥量,使用完成时候解锁它。
头文件:
< pthread.h >
锁初始化操作:
int pthread_mutex(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr)
参数:
mutexattr是设置互斥量的属性,而属性控制着互斥量的行为。属性类型默认为fast。其中如果不改变类型的值的话,一种死锁就无法解决。比如已对加了锁的互斥量调用pthread_mutex_lock,程序就会进入死锁状态。
加锁操作:
int pthread_mutex_unlock(pthread_mutex_t *mutex)
解锁操作:
int pthread_mutex_unlock(pthread_mutex_t *mutex)
释放锁资源操作:
int pthread_mutex_destroy(pthread_mutex_t *mutex)
3. 条件变量
条件变量,顾名思义就是在满足某种条件下才做什么,在不满足条件下就是一直等待。一般与互斥变量或者互斥锁一起使用。
条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉此改变,因此必须锁定互斥量以后才能计算条件。
相关操作:
int pthread_cond_init(pthread_cond_t *restrict cond,pthread_condattr *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 timeout)
唤醒线程操作
int pthread_cond_signal(pthread_cond_t *cond)
int pthread_cond_broadcast(pthread_cond_t *cond);
上述所有操作函数都是成功返回0