1.互斥量
互斥变量用pthead_mutex_t数据类型来表示,在使用互斥变量之前,必须首先对它进行初始化,可以把它置为常量PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量),也可以能过调用pthread_mutex_init函数进行初始化。如果动态地分配互斥量(例如通过调用malloc)函数,那么释放内存前需要使用pthread_mutex_destroy.
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexarrt_t * restrict arrt);
int pthread_mutex_destroy(pthread_mutex_t &mutex);
返回值:成功返回0,否则返回错误编号。
要用默认的属性初始化互斥量,只需把attr设置为NULL。
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值:成功返回0,否则返回错误编号。
#include
#include
struct foo {
int f_count;
pthread_mutex_t f_lock;
/* ... more stuff here ... */
};
struct foo *
foo_alloc(void) /* allocate the object */
{
struct foo *fp;
if ((fp = malloc(sizeof(struct foo))) != NULL) {
fp->f_count = 1;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
free(fp);
return(NULL);
}
/* ... continue initialization ... */
}
return(fp);
}
void
foo_hold(struct foo *fp) /* add a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
fp->f_count++;
pthread_mutex_unlock(&fp->f_lock);
}
void
foo_rele(struct foo *fp) /* release a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
if (--fp->f_count == 0) { /* last reference */
pthread_mutex_unlock(&fp->f_lock);
pthread_mutex_destroy(&fp->f_lock);
free(fp);
} else {
pthread_mutex_unlock(&fp->f_lock);
}
}
2.避免死锁
如果线程试图对同一个互斥量加锁两次,那么它自身就会陷入死锁状态。
一个线程试图以与另一个线程相反的顺序销售互斥量时,才可能出现死锁。
实例:
#include
#include
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int lock_var;
time_t end_time;
void pthread1(void *arg);
void pthread2(void *arg);
int main(int argc, char *argv[])
{
pthread_t id1,id2;
pthread_t mon_th_id;
int ret;
end_time = time(NULL)+10;
/*互斥锁初始化*/
pthread_mutex_init(&mutex,NULL);
/*创建两个线程*/
ret=pthread_create(&id1,NULL,(void *)pthread1, NULL);
if(ret!=0)
perror("pthread cread1");
ret=pthread_create(&id2,NULL,(void *)pthread2, NULL);
if(ret!=0)
perror("pthread cread2");
pthread_join(id1,NULL);
pthread_join(id2,NULL);
exit(0);
}
void pthread1(void *arg)
{
int i;
while(time(NULL) < end_time)
{
/*互斥锁上锁*/
if(pthread_mutex_lock(&mutex)!=0)
{
perror("pthread_mutex_lock");
}
else
printf("pthread1:pthread1 lock the variable\n");
for(i=0;i<2;i++){
sleep(1);
lock_var++;
}
/*互斥锁接锁*/
if(pthread_mutex_unlock(&mutex)!=0){
perror("pthread_mutex_unlock");
}
else
printf("pthread1:pthread1 unlock the variable\n");
sleep(1);
}
}
void pthread2(void *arg)
{
int nolock=0;
int ret;
while(time(NULL) < end_time)
{
/*测试互斥锁*/
ret=pthread_mutex_trylock(&mutex);
if(ret==EBUSY)
printf("pthread2:the variable is locked by pthread1\n");
else
{
if(ret!=0)
{
perror("pthread_mutex_trylock");
exit(1);
}
else
printf("pthread2:pthread2 got lock.The variable is%d\n",lock_var);
/*互斥锁接锁*/
if(pthread_mutex_unlock(&mutex)!=0)
{
perror("pthread_mutex_unlock");
}
else
printf("pthread2:pthread2 unlock the variable\n");
}
sleep(3);
}
}
3.读写锁
1)多个读者可以同时进行读
2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行)
3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);
初始化读/写锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
锁定读/写锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
读取读/写锁上的锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
写读/写锁上的锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
解除读/写锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
成功返回0,否则返回错误编号
实例:
#include
#include
struct job {
struct job *j_next;
struct job *j_prev;
pthread_t j_id; /* tells which thread handles this job */
/* ... more stuff here ... */
};
struct queue {
struct job *q_head;
struct job *q_tail;
pthread_rwlock_t q_lock;
};
/*
* Initialize a queue.
*/
int
queue_init(struct queue *qp)
{
int err;
qp->q_head = NULL;
qp->q_tail = NULL;
err = pthread_rwlock_init(&qp->q_lock, NULL);
if (err != 0)
return(err);
/* ... continue initialization ... */
return(0);
}
/*
* Insert a job at the head of the queue.
*/
void
job_insert(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
jp->j_next = qp->q_head;
jp->j_prev = NULL;
if (qp->q_head != NULL)
qp->q_head->j_prev = jp;
else
qp->q_tail = jp; /* list was empty */
qp->q_head = jp;
pthread_rwlock_unlock(&qp->q_lock);
}
/*
* Append a job on the tail of the queue.
*/
void
job_append(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
jp->j_next = NULL;
jp->j_prev = qp->q_tail;
if (qp->q_tail != NULL)
qp->q_tail->j_next = jp;
else
qp->q_head = jp; /* list was empty */
qp->q_tail = jp;
pthread_rwlock_unlock(&qp->q_lock);
}
/*
* Remove the given job from a queue.
*/
void
job_remove(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
if (jp == qp->q_head) {
qp->q_head = jp->j_next;
if (qp->q_tail == jp)
qp->q_tail = NULL;
} else if (jp == qp->q_tail) {
qp->q_tail = jp->j_prev;
if (qp->q_head == jp)
qp->q_head = NULL;
} else {
jp->j_prev->j_next = jp->j_next;
jp->j_next->j_prev = jp->j_prev;
}
pthread_rwlock_unlock(&qp->q_lock);
}
/*
* Find a job for the given thread ID.
*/
struct job *
job_find(struct queue *qp, pthread_t id)
{
struct job *jp;
if (pthread_rwlock_rdlock(&qp->q_lock) != 0)
return(NULL);
for (jp = qp->q_head; jp != NULL; jp = jp->j_next)
if (pthread_equal(jp->j_id, id))
break;
pthread_rwlock_unlock(&qp->q_lock);
return(jp);
}
这个例子中,不管什么时候需要增加一个作业也不能队列中或者从队列中删除作业,都用写模式锁住队列的读写锁。不管何时搜索队列,首先需要获取读模式下的锁,允许所有的工作线程并发地搜索队列。在这种情况下,只有线程搜索队列的频率远远高于增加或者删除作业时,使用读写锁才可能改善性能。
4.条件变量
静态创建:pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
动态创建:pthread_cond _t cond;
pthread_cond_init(&cond,NULL);
其中的第二个参数NULL表示条件变量的属性,虽然POSIX中定义了条件变量的属性,但在LinuxThread中并没有实现,因此常常忽略
实例:
#include
#include
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
int count=5;
void *decrement(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
while(count<=0)
{
printf("count<=0,thread1 is hanging!\n");
pthread_cond_wait(&cond,&mutex);
sleep(1);
printf("sleep!\n");
}
count=count-1;
pthread_mutex_unlock(&mutex);
if(count==9)
{
printf("count=9,thread1 is over!\n");
return NULL;
}
}
}
void *increment(void *arg)
{sleep(1);
while(1)
{
pthread_mutex_lock(&mutex);
count=count+1;
if(count>0)
{
printf("count=%d,change cond state!\n",count);
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
if(count==10)
{
printf("count=10,thread2 is over!\n");
return NULL;
}
}
}
int main()
{
int i1=1,i2=1;
pthread_t id1,id2;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&id1,NULL,decrement,NULL);
pthread_create(&id2,NULL,increment,NULL);
i2=pthread_join(id2,NULL);
i1=pthread_join(id1,NULL);
if((i2==0)&&(i1==0))
{
printf("count=%d,the main thread!\n",count);
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
return 0;
}
}