互斥(锁的机制)
由于互斥锁,自旋锁,读写锁作用与函数名都类似,所以这里我们只讨论互斥锁。互斥锁是用一种简单的加锁方法来控制对共享资源的原子操作。这个互斥锁只有两种状态,也就是上锁和解锁,可以把互斥锁看作某种意义上的全局变量。在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行操作。若其他线程希望上锁一个已经被上锁的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止。那么这把互斥锁保证让每个线程对共享资源按顺序进行原子操作。
互斥锁函数
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
代码示例
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<string.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *func(void *arg)
{
int i=0;
pthread_mutex_lock(&mutex);
for(i=0; i<3; i++)
{
printf("thread %u running %d times\n",pthread_self(),i+1);
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main()
{
int i=0;
pthread_t tid[10];
for(i=0; i<5; i++)
{
pthread_create(&tid[i],NULL,func,NULL);
}
for(i=0; i<5; i++)
{
pthread_join(tid[i],NULL);
}
return 0;
}
同步(条件变量)
与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁一起使用。条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。条件的检测是在互斥锁的保护下进行的。如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件 变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两进程共享可读写的内存,条件变量可以被用来实现这两进程间的线程同步。
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
利用互斥锁与条件变量实现生产者消费者模型
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<string.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int product;
void *produce(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
product++;
printf("thread %u produce ,now have %d product\n",pthread_self(),product);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
sleep(1);
}
pthread_exit(NULL);
}
void *consume(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
while(product==0)
{
printf("no product! waiting\n");
pthread_cond_wait(&cond,&mutex);
printf("product coming!\n");
}
product--;
printf("thread %u consume ,now have %d product\n",pthread_self(),product);
pthread_mutex_unlock(&mutex);
sleep(1);
}
pthread_exit(NULL);
}
int main()
{
pthread_t tid[4];
int pro=1,cos=3,i;
for(i=0; i<cos; i++)
{
pthread_create(&tid[i],NULL,consume,NULL);
}
for(; i<pro+cos; i++)
{
pthread_create(&tid[i],NULL,produce,NULL);
}
for(i=0; i<4; i++)
{
pthread_join(tid[i],NULL);
}
return 0;
}