首先来说线程间的通信。因为多个线程是共享进程的空间的,所以线程之间的通信比较简单,主要是利用全局变量的方法。全局变量对进程内的的所有线程都是可见的,所以多个线程可以通过操作全局变量达到相互通信的效果。但是这也存在一个问题,就是“资源”的竞争。
这里所说的资源指的就是全局变量,正是因为这种竞争(因为多线程是同时运行的,而我们往往不会去控制线程运行的顺序,不然也不会用多线程了),导致可一些我们不愿见到的结果,所以我们每个线程对全局变量的操作都希望是原子性的。
为了解决这个问题在线程见引入了三种同步互斥机制,分别是信号量,互斥锁,条件变量。
具体的函数应用如下:
信号量
#include
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能:信号量的初始化。
参数:
sem:就是信号量的标识符
pshared: 0,表示该信号量用于线程之间的通信。
非0, 表示该信号量用于进程程之间的通信。
value:非负的整数,就是信号量的初值。
如果为0, 表示没有资源。
int sem_wait(sem_t *sem);
功能:阻塞申请信号量资源, 当信号量的值等于0时,睡眠等待。
一旦申请成功,那么信号量的值就会被减1.
参数:sem:
int sem_trywait(sem_t *sem);
功能:非阻塞申请信号量资源,如果申请不到资源,那么该函数立刻返回。
int sem_post(sem_t *sem);
功能:释放信号量资源
释放成功,信号量的值加1.
int sem_getvalue(sem_t *sem, int *svalue);
功能:获得当前信号量的值。
参数:sem,指定要获得的信号量
svalue,用于保存获得的信号量的值。
int sem_destroy(sem_t *sem);
功能:销毁无名信号量。
线程互斥锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
功能:产生一把锁
参数:mutex: 线程锁的标识符
attr: 设置线程锁的属性,通常为NULL。
pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL);
int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:上锁, 阻塞等待,直到能够得到这把锁。
int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:解锁。
int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:就是销毁一把锁。
条件变量:
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
功能:初始化条件变量。
参数:cond:条件变量的标识符
atrr:条件变量的属性,通常为NULL。
pthread_cond_t cond;
pthread_cond_init(&cond, NULL);
int pthread_cond_signal(pthread_cond_t *cond);
功能:就是给一个需要该条件变量的线程发送唤醒的信号。
int pthread_cond_broadcast(pthread_cond_t *cond);
功能:给所有需要该条件变量的线程都发送唤醒信号。
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
功能:就是导致线程睡眠在此函数上,直到有线程给它发送条件变量的唤醒信号。
参数:cond:需要改条件变量
mutex:就是一个锁。
pthread_cond_wait():先将锁解开,然后进入睡眠,当被唤醒的时候需要重新加锁(如果此时得不到锁,那么继续睡眠)。
int pthread_cond_destroy(pthread_cond_t *cond);
功能:销毁条件变量。
这些函数的具体用法在上课时候我们已经学过,不再做更为具体的介绍,希望同学们多加练习。这里主要是总结下三者的应用。
这三种机制中,信号量和条件变量属于一种阻塞通知的机制。采用阻塞的方法,让一个进程中只有一个线程能“顺利执行”,执行完毕后再通知其他线程执行。而互斥锁是典型的互斥机制,对资源加以保护,在这期间不允许其他现场对保护的内容进行读写操作。通过信号量和条件变量都可以实现经典的生产者消费者模式。