互斥量从本质上讲是一把锁,在访问共享资源前对互斥量加锁,在访问完成后释放互斥量。对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程都会被阻塞直到当前线程释放该互斥锁。如果释放互斥量时有一个以上的线程阻塞,那么所有该锁上的阻塞线程都会变成可运行状态,第一个变为运行的线程就可以对互斥量进行加锁,其他线程就会看到互斥量依然是锁着的,只能再次等待该互斥量重新变成可有。在这种方式下,每次只有一个线程可以向前执行。
如果一个互斥锁或者条件变量存放在多个进程间的共享的某个内存区中,那么Posix还允许它用于进程间的同步。
互斥锁通常用于保护由多个线程或者多个进程分享的共享数据。
互斥量是用pthread_mutex_t数据类型表示的。
初始化及销毁:
pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrictattr);
pthread_mutex_destroy(pthread_mutex_t *mutex);
加锁及解锁:
pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_unlock(pthread_mutex_t *mutex);
一个demo:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
//需要同步保护的结构体
struct foo
{
int f_cnt;
pthread_mutex_t f_lock;
int f_id;
int f_data;
};
//alloct the obj
struct foo *foo_alloc(int id)
{
struct foo *fp;
if ((fp = malloc(sizeof(struct foo))) != NULL)
{
fp->f_cnt = 1;
fp->f_id = id;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0)
{
free(fp);
fp = NULL;
return NULL;
}
}
return fp;
}
//add a reference to the obj
void foo_hold(struct foo *fp)
{
pthread_mutex_lock(&fp->f_lock);
fp->f_cnt++;
pthread_mutex_unlock(&fp->f_lock);
}
//release a reference to the obj
void foo_rele(struct foo *fp)
{
pthread_mutex_lock(&fp->f_lock);
if (--fp->f_cnt == 0)//last reference
{
pthread_mutex_unlock(&fp->f_lock);
pthread_mutex_destroy(&fp->f_lock);
free(fp);
}
else
{
pthread_mutex_unlock(&fp->f_lock);
}
}
void *thread1(void *args)
{
struct foo *fp = (struct foo*)args;
while(fp->f_data <= 200)
{
foo_hold(fp);
fp->f_data++;
printf("thread1 f_data = %d\n", fp->f_data);
foo_rele(fp);
sleep(1);
}
}
void *thread2(void *args)
{
struct foo *fp = (struct foo*)args;
while (fp->f_data <= 200)
{
foo_hold(fp);
fp->f_data++;
printf("thread2 f_data = %d\n", fp->f_data);
foo_rele(fp);
sleep(1);
}
}
int main()
{
pthread_t tid1, tid2;
struct foo *fp = foo_alloc(1);
pthread_create(&tid1, NULL, thread1, (void*)fp);
pthread_create(&tid2, NULL, thread2, (void*)fp);
pthread_join(tid1, NULL);
exit(0);
}