/* 未完待续 */
锁就是一个变量,因此在使用前要声明一种类型的锁变量。这个锁变量保存了锁在某一时刻的状态,可用或占用等。
互斥锁
- pthread_mutex_init(&lock, NULL) 动态初始化互斥锁;
- phtread_mutex_destory() 销毁互斥锁;
- pthread_mutex_lock(&lock) 加锁
- pthread_mutex_unlock(&lock) 释放互斥锁
如果在线程A调用pthread_mutex_lock()函数时,没有其他线程持有该锁,则线程A获取该锁并进入临界区;
如果另一个线程B持有该锁,线程A尝试获取该锁不会从这个调用返回,直到获取到锁(意味着线程B释放了锁)。
2. 条件变量
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。
- 静态初始化条件变量
pthread_cond_t = PTHREAD_COND_INITIALIZER
也可也采用动态初始化的方法,调用pthread_cond_init(),对应的释放函数为pthread_cond_destory()
要使用条件变量,必须要持有该锁才能调用如下函数:
- pthread_cond_wait(&cond,&lock) 使线程进入休眠状态(睡眠时释放锁,唤醒时加锁)
- pthrad_cond_signal(&cond) 激活等待列表中的线程
3. 信号量
信号量是一个整数值的对象
int sem_init (sem_t *sem, int pshared, unsigned int value);
这个函数的作用是对由sem指定的信号量进行初始化,设置好它的共享选项,并指定一个整数类型的初始值。pshared参数控制着信号量的类型。Value为信号量的初始值。
int sem_destroy (sem_t *sem)对应的去初始化函数
int sem_post(sem_t * sem);
用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。
函数的作用是给信号量的值加上一个“1”,它是一个“原子操作”---即同时对同一个信号量做加“1”操作的两个线程是不会冲突的。
int sem_wait(sem_t * sem);
被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。
函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,介信号量的值将减到1。如果对一个值为0的信号量调用sem_wait(),这个函数就会地等待直到有其它线程增加了这个值使它不再是0为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值,那么当它被第三个线程增加一个“1”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。
#include "stdio.h"
#include "pthread.h"
#include "semaphore.h"
sem_t g_sem;
void* fun1(void *arg)
{
printf("thread 1 start\n");
sem_wait(&g_sem);
printf("thread 1 sem_wait 1\n");
sem_wait(&g_sem);
printf("thread 1 sem_wait 2\n");
return;
}
void* fun2(void *arg)
{
printf("thread 2 start\n");
sem_post(&g_sem);
printf("thread 2 sem_post\n");
return;
}
int main(void)
{
pthread_t pthread1;
pthread_t pthread2;
int res = 0;
/* 信号量的初始值为1 */
sem_init(&g_sem, 0, 1);
res = pthread_create(&pthread1, NULL, fun1, NULL);
sleep(1);
pthread_create(&pthread1, NULL, fun2, NULL);
sleep(1);
sem_destroy(&g_sem);
return 0;
}
运行结果
thread 1 start
thread 1 sem_wait 1
thread 2 start
thread 2 sem_post
thread 1 sem_wait 2
说明:信号量初始值为1,进入线程1后,第一次执行sem_wait,信号量减一,第二次执行sem_wait时,当前信号量值为0,此时线程1阻塞。知道线程2,执行sem_post,信号量加1,激活被阻塞的线程1
Ref: https://blog.csdn.net/linfeng999/article/details/6291824
4. 读写锁
多个读者可以并发读,写着只能有一个写者
typedef struct _rwlock_t
{
sem_t lock;
sem_t writelock;
int readers;
}rwlock_t;
void rwlock_int(rwlock_t *rw)
{
rw->readers = 0;
sem_init(&rw->lock, 0, 1);
sem_init(&rw->writelock, 0, 1);
}
void rwlock_acquire_readlock(rwlock_t *rw)
{
sem_wait(&rw->lock);
rw->readers++;
if(rw->readers == 1)
sem_wait(&rw->writelock); // first reader acquires writelock
sem_post(&rw->lock);
}
void rwlock_release_readlock(rwlock_t *rw)
{
sem_wait(&rw->lock);
rw->readers--;
if(rw->readers == 0)
sem_post(&rw->writelock); // last reader releases writelock
sem_post(&rw->lock);
}
void rwlock_acquire_writelock(rwlock_t *rw)
{
sem_wait(&rw->writelock);
}
void rwlock_release_writelock(rwlock_t *rw)
{
sem_post(&rw->writelock);
}