1. 互斥量
本质上说就是一把锁, 提供对共享资源的保护访问
1-1. 初始化
静态分配的互斥量, 可以设置为 PTHREAD_MUTEX_INITIALIZER, 或调用 pthread_mutex_init
动态分配的互斥量, 在申请内存 (malloc) 之后, 通过 pthread_mutex_init 初始化, 并在释放内存 (free) 前调用 pthread_mutex_destroy
1-1-1. int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr);
1-1-2. int pthread_mutex_destroy(pthread_mutex_t *mutex);
返回值: 成功则返回0, 出错则返回错误编号
1-2. 互斥操作
对共享资源的访问, 要对互斥量进行加锁, 如果互斥量已经上了锁, 调用线程会阻塞, 直到互斥量被解锁
在完成了对共享资源的访问后, 要对互斥量进行解锁
1-2-1. int pthread_mutex_lock(pthread_mutex_t *mutex);
1-2-2. int pthread_mutex_trylock(pthread_mutex_t *mutex);
非阻塞调用模式, 如果互斥量没被锁住, 将把互斥量加锁, 并获得对共享资源的访问权限
如果互斥量被锁住了, 将不会阻塞等待而直接返回 EBUSY, 表示共享资源处于忙状态
返回值: 成功则返回0, 出错则返回错误编号
1-3. 解锁函数
1-3-1. int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值: 成功则返回0, 出错则返回错误编号
1-4. 简单实例
/* gcc -o lock -lpthread lock.c */
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
static pthread_mutex_t testlock;
pthread_t test_thread;
void *test()
{
int i;
pthread_mutex_lock(&testlock);
for(i = 0; i < 5; i++)
{
printf("[%d] thread running... \n", i + 1);
sleep(2);
}
pthread_mutex_unlock(&testlock);
}
int main()
{
pthread_mutex_init(&testlock, NULL);
pthread_create(&test_thread, NULL, test, NULL);
sleep(1);
int locked;
while(1)
{
locked = pthread_mutex_trylock(&testlock);
if(locked)
{
printf("locked, I'm waiting...\n");
sleep(1);
continue;
}
else
break;
}
printf("main lock \n");
// pthread_mutex_lock(&testlock);
printf("main doing some thing...\n");
sleep(1);
printf("main unlock \n");
pthread_mutex_unlock(&testlock);
printf("waiting for sub thread...\n");
pthread_join(test_thread, NULL);
pthread_mutex_destroy(&testlock);
exit(0);
}
================================================================================
2. 条件变量
利用线程间共享的全局变量进行同步的一种机制
包括两个动作: 一个线程等待 "条件变量的条件成立" 而挂起, 另一个线程使 "条件成立" (给出条件成立信号)
为了防止竞争, 条件变量的使用总是和一个互斥锁结合在一起
2-1. 创建和注销
2-1-1. 静态创建
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
2-1-2. 动态创建
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
2-1-3. 注销
int pthread_cond_destroy(pthread_cond_t *cond)
只有在没有线程在该条件变量上等待的时候才能注销这个条件变量, 否则返回 EBUSY
2-2. 等待和激发
2-2-1. 无条件等待
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
2-2-2. 计时等待
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
如果在给定时刻前条件没有满足, 则返回 ETIMEOUT, 结束等待, 其中 abstime 是绝对时间形式, 0 表示格林尼治时间1970年1月1日0时0分0秒
2-2-3. 激发条件
pthread_cond_signal(pthread_cond_t *cond), 激活一个等待该条件的线程, 存在多个等待线程时按入队顺序激活其中一个
pthread_cond_broadcast(pthread_cond_t *cond), 激活所有等待线程, 两者如果没有等待的线程, 则什么也不做
2-3. 简单实例
/* gcc -o cond cond.c -lpthread */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t m;
pthread_cond_t c;
void *t1(void *arg)
{
printf("thread1 : t1() start!\n");
pthread_mutex_lock(&m);
printf("thread1 : t1() waiting...\n");
pthread_cond_wait(&c, &m); // 等待
printf("thread1 : t1() ok!\n");
pthread_mutex_unlock(&m);
printf("thread1 : t1() end!\n");
}
void *t2(void *arg)
{
printf("thread2 : t2() start!\n");
sleep(5);
printf("thread2 : t2() wake up thread1!\n");
pthread_cond_signal(&c); // 唤醒 thread1
printf("thread2 : t2() end!\n");
}
int main(int argc, char **argv)
{
pthread_t a, b;
pthread_mutex_init(&m, NULL);
pthread_create(&a, NULL, (void *)t1, NULL);
pthread_create(&b, NULL, (void *)t2, NULL);
sleep(10);
exit(0);
}
0 件のコメント:
コメントを投稿