linux线程--线程间同步机制
linux实现线程间同步主要有如下三个手段:
mutex(互斥变量)/cond(条件变量)/sem(信号量)
mutex互斥变量
互斥变量是实现线程同步的一个重要手段,通过对互斥变量加解锁机制,可以实现线程的同步。
一个线程对一个互斥变量加锁,而其他任何一个线程想再次对互斥变量加锁时都会被阻塞,直到加锁线程释放互斥锁。
互斥锁有一个很明显的特点就是哪个线程对互斥变量加锁,必须有哪个线程对互斥变量解锁
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <queue>
#include "main.h"
using namespace std;
pthread_mutex_t mutex;
queue<int>qe;
void* threadFunc1(void* arg)
{
for (int index = 0; index<10; index++) {
pthread_mutex_lock(&mutex);
printf("this is func1
");
qe.push(index);
pthread_mutex_unlock(&mutex);
}
return nullptr;
}
void* threadFunc2(void* arg)
{
for (int index = 0; index<10; index++) {
pthread_mutex_lock(&mutex);
printf("this is func2
");
printf("this is %d
", qe.front());
qe.pop();
pthread_mutex_unlock(&mutex);
}
return nullptr;
}
int main()
{
pthread_mutex_init(&mutex, NULL);
pthread_t pid1, pid2, pid3,pid4;
pthread_create(&pid1, NULL, threadFunc1, NULL);
pthread_create(&pid2, NULL, threadFunc2, NULL);
void* ret;
pthread_join(pid1, &ret);
pthread_join(pid2, &ret);
pthread_mutex_destroy(&mutex); // 销毁线程锁
return 0;
}
pthread_cond_t条件变量
条件变量是实现线程同步的另一个重要手段,可以使用条件变量等待另一个线程的结束,条件变量一般痛互斥变量一起使用
条件变量的一个重要表象就是一个线程等待另外的线程发送信号
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include "main.h"
using namespace std;
pthread_mutex_t mutex;
queue<int>qe;
uint32_t sum = 0;
void* threadFunc1(void* arg)
{
pthread_mutex_lock(&mutex);
sum++
pthread_mutex_unlock(&mutex);
return nullptr;
}
void* threadFunc2(void* arg)
{
pthread_mutex_lock(&mutex);
if (sum >= 100) {
printf("sum is reach 100
");
sum = 0;
} else if (sum < 100) {
sleep(1);
}
pthread_mutex_unlock(&mutex);
return nullptr;
}
int main()
{
pthread_mutex_init(&mutex, NULL);
pthread_t pid1, pid2, pid3,pid4;
pthread_create_t(pid1, NULL, threadFunc1, NULL);
pthread_create_t(pid2, NULL, threadFunc2, NULL);
void* ret;
pthread_join(pid1, &ret);
pthread_join(pid2, &ret);
pthread_mutex_destroy(&mutex); // 销毁线程锁
return 0;
}
但是这样会引起如下问题:
1、大多数情况下,sum的数值不会到达100,就是函数大部分时间会进入else分支,sleep(1),这样会引起pid4的执行效率变慢,且sleep(1)之后,sum的数值可能已经非常大了。
2、sleep的数值取值非常麻烦,取得小会频繁的sleep,浪费CPU资源;取的大会无法把控
这个时候条件变量就起作用了,我们可以设置一个条件变量,当条件满足时,向等待的线程发送信号。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <queue>
#include <vector>
#include "main.h"
using namespace std;
pthread_mutex_t mutex;
queue<int>qe;
uint32_t sum = 0;
pthread_cond_t cond_sum_ready = PTHREAD_COND_INITIALIZER;
static void* threadFunc1(void* arg)
{
pthread_mutex_lock(&mutex);
sum++;
printf("sum = %d
", sum);
if (sum >= 100) {
pthread_cond_signal(&cond_sum_ready);
}
pthread_mutex_unlock(&mutex);
return nullptr;
}
static void* threadFunc2(void* arg)
{
pthread_mutex_lock(&mutex);
while(sum < 100) {
printf("pthread4 unlock mutex
");
pthread_cond_wait(&cond_sum_ready, &mutex);
}
printf("sum is reach 100");
sum = 0;
pthread_mutex_unlock(&mutex);
return nullptr;
}
int main()
{
pthread_mutex_init(&mutex, NULL);
pthread_t pid1, pid2, pid3, pid4;
pthread_create(&pid1, NULL, threadFunc1, NULL);
pthread_create(&pid2, NULL, threadFunc1, NULL);
pthread_create(&pid3, NULL, threadFunc1, NULL);
pthread_create(&pid4, NULL, threadFunc2, NULL);
void* ret;
pthread_join(pid1, &ret);
pthread_join(pid2, &ret);
pthread_join(pid3, &ret);
pthread_join(pid4, &ret);
pthread_mutex_destroy(&mutex); // 销毁线程锁
return 0;
}