目录
1,阻塞在条件变量上的线程被唤醒后需抢锁
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int nready = 0;
struct timespec timestamp;
// 模式1:抢锁冲突严重
void *producter(void *arg)
{
char date_time[64];
struct tm t;
while (1)
{
pthread_mutex_lock(&mutex);
if (nready >= 1) {
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("producer tid=%d, before notify, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
pthread_cond_signal(&cond);
//sleep(10);
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("producer tid=%d, after notify, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
}
nready++;
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("producer tid=%d, will unlock, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
pthread_mutex_unlock(&mutex);
sleep(2);
//sched_yield(); // 与让不让cpu无关
}
return NULL;
}
// 模式2:避免抢锁冲突
void *producter(void *arg)
{
char date_time[64];
struct tm t;
while (1)
{
pthread_mutex_lock(&mutex);
nready++;
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("producer tid=%d, will unlock, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
pthread_mutex_unlock(&mutex);
if (nready >= 1) {
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("producer tid=%d, before notify, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
pthread_cond_signal(&cond);
//sleep(10);
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("producer tid=%d, after notify, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
}
//sched_yield(); // 与让不让cpu无关
}
return NULL;
}
void *consumer(void *arg)
{
char date_time[64];
struct tm t;
while (1) {
pthread_mutex_lock(&mutex);
while (nready <= 0) {
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("consumer tid=%d, will sleep, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
pthread_cond_wait(&cond, &mutex);
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("consumer tid=%d, wait return, in while, already awake up, and get lock, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
}
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("consumer tid=%d, wait return, out while, already awake up, and get lock, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
nready--;
clock_gettime(CLOCK_REALTIME, ×tamp);
strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp.tv_sec, &t));
printf("consumer tid=%d, wait return, out while, after --nready, already awake up, and get lock, clock_gettime: date_time=%s, tv_nsec=%ld, nready=%d.\n", pthread_self(), date_time, timestamp.tv_nsec, nready);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void)
{
int pthread_num = 1;
pthread_t ptid[pthread_num];
pthread_t ctid[pthread_num];
int i = 0;
for (i = 0; i < pthread_num; i++) {
pthread_create(&ctid[i], NULL, consumer, NULL);
}
for (i = 0; i < pthread_num; i++) {
pthread_create(&ptid[i], NULL, producter, NULL);
}
for (i = 0; i < pthread_num; i++) {
pthread_join(ctid[i], NULL);
}
for (i = 0; i < pthread_num; i++) {
pthread_join(ptid[i], NULL);
}
return 0;
}
模式1:抢锁冲突严重
1,pthread_cond_wait 解锁和阻塞这两个步骤是原子的。但是被唤醒和上锁不是原子的,需要等生产者解锁后,才会去抢互斥锁(消费者和生产者抢锁,以及消费者之间抢锁)。
2,处于互斥锁中的pthread_cond_signal 发送信号, pthread_cond_wait被唤醒后,需要等发送信号的那个生产者解锁后,才会去抢互斥锁(消费者和生产者抢锁,以及消费者之间抢锁)。
// 生产者及时发送信