互斥锁:(也称之为互斥量)。
每个线程在对资源操作前都尝试先加锁,成功加锁才能操作,操作结束解锁。
但通过“锁”就将资源的访问变成互斥操作,而后与时间有关的错误也不会再产生了
但,应注意:同一时刻,只能有一个线程持有该锁。
当A线程对某个全局变量加锁访问,B在访问前尝试加锁,拿不到锁,B阻塞。C线程不去加锁,而直接访问该全局变量,依然能够访问,但会出现数据混乱。
条件变量(Condition Variable)是一种同步机制,用于协调线程之间的操作。它通常与互斥锁(Mutex)结合使用,以实现线程间的协作。
条件变量允许线程在等待某些特定条件时被阻塞,直到其他线程在满足这些条件时通知它们。在等待条件期间,线程可以释放互斥锁,从而允许其他线程访问共享资源,同时避免竞争条件。(这是为什么互斥锁和条件变量可以结合的关键条件)
当某个线程满足条件时,它可以使用条件变量通知正在等待的线程。在接收到通知后,线程可以重新获取互斥锁,并继续执行。
条件变量在编写多线程应用程序时非常有用,因为它们可以帮助避免死锁,并允许线程在满足特定条件时才进行操作,从而提高应用程序的效率。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>
static char g_buf[1000];
static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t g_tConVar = PTHREAD_COND_INITIALIZER;
//按上面那么写 就不用初始化 如果 单单这么写 “pthread_mutex_t g_tMutex” 就要下面的初始化
//pthread_cond_init( &g_tConVar , NULL ); //初始化条件信号量
//pthread_mutex_init( &g_tMutex , NULL ); //初始化互斥量
static void *my_thread_func (void *data)
{
while (1)
{
/* 等待通知 */
pthread_mutex_lock(&g_tMutex);/*第二步 加锁*/
printf("wait\n");
pthread_cond_wait(&g_tConVar, &g_tMutex);/*第三步:等待并解锁 第七步:唤醒并加锁 解出阻塞,程序向下运行 */
/* 打印 */
printf("recv: %s\n", g_buf);
pthread_mutex_unlock(&g_tMutex); /*第八步 解锁*/
printf("recv:%s\n", g_buf);
}
return NULL;
}
int main(int argc, char **argv)
{
pthread_t tid;
int ret;
char buf[1000];
/* 1. 创建"接收线程" */
ret = pthread_create(&tid, NULL, my_thread_func, NULL); /*第一步:由于程序执行的先后 性,先进入该线程 当然在这个语句后面加入延迟保证先执行这个线程*/
if (ret)
{
printf("pthread_create err!\n");
return -1;
}
/* 2. 主线程读取标准输入, 发给"接收线程" */
while (1)
{
fgets(buf, 1000, stdin);
pthread_mutex_lock(&g_tMutex);/*第四步:因为上面解锁了 所以我这里可以重新加锁*/
printf("lock\n");
memcpy(g_buf, buf, 1000);
pthread_cond_signal(&g_tConVar); /* 通知接收线程 */ /*第五步:唤醒条件变量*/
printf("unlock\n");
pthread_mutex_unlock(&g_tMutex);/*第六步 紧接着 解锁*/
}
return 0;
}
编译:
gcc pthread5.c -o pthread5 -lpthread
结果: