我理解的互斥量本质上就是一把锁,一把加在一个线程要使用共享资源前的锁,一个线程要使用共享的资源,对互斥量进行设置(加锁),把需要用到的资源给锁定,(当一个以上的线程需要访问动态分配的对象时)不让其他线程碰,当该线程用完这部分资源后,再释放互斥量(解锁),把这段资源解除锁定,让所有线程都可以修改或者说使用这部分资源。
互斥量只是个锁,只是线程当中创建的一个特殊类型的变量而已,并非是线程本身,甚至不是线程处理中的主角,互斥量的存在就是为了锁定而已。
下面是书中的示例代码(描述了用于保护某个数据结构的互斥量是如何运行的):
第一部分
定义了一个结构体,结构体里面定义了三个变量,仅有f_lock是互斥量的类型(pthread_mutex_t),其他两个是正常的int变量,可以看出,所处理的主角的是foo,而互斥量只是充当其的一个属性而已。
#include <stdio.h>
#include <pthread.h>
struct foo
{
int f_count;
pthread_mutex_t f_lock;
int f_id;
};
第二部分
定义将foo初始化功能的函数,默认的,初始化的时候线程数为1,并且,因为只有一个线程,不存在其他线程的争夺资源,所以不需要考虑加不加锁的问题(所以初始化的时候,没有调用pthread_mutex_lock函数)。
struct foo* foo_alloc(int id)
{
struct foo* fp;
if ((fp = malloc(sizeof(struct foo)))!= NULL) {
fp->f_count = 1;
fp->f_id = id;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
free(fp);
}
}
return(fp);
}
第三部分
定义当多个线程存在时,对当前线程的锁定保护操作,可以发现,只要执行foo_hold,就会先执行锁定函数,把当前线程对应的资源给锁住,然后,再进行其他操作,当处理完了,再进行解锁操作,
void foo_hold(struct foo* fp)
{
pthread_mutex_lock(&fp->f_lock); //加锁
fp->f_count++;
pthread_mutex_unlock(&fp->f_lock); //去锁
}
第四部分
当都使用完之后,要对互斥量变量进行析构消除,如果没使用完,就接着操作。
void foo_rele(struct foo *fp)
{
pthread_mutex_lock(&fp->f_lock);
if (--fp->f_count == 0)
{
pthread_mutex_unlock(fp->f_lock);
pthread_mutex_destroy(fp->f_lock);
free(fp);
}
else
{
pthread_mutex_unlock(fp->f_lock);
}
}
总体代码
#include <stdio.h>
#include <pthread.h>
struct foo
{
int f_count;
pthread_mutex_t f_lock;
int f_id;
};
struct foo *foo_alloc(int id)
{
struct foo *fp;
if ((fp = malloc(sizeof(struct foo)))!= NULL) {
fp->f_count = 1;
fp->f_id = id;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
free(fp);
}
}
return(fp);
}
void foo_hold(struct foo *fp)
{
pthread_mutex_lock(&fp->f_lock);
fp->f_count++;
pthread_mutex_unlock(&fp->f_lock);
}
void foo_rele(struct foo* fp)
{
pthread_mutex_lock(&fp->f_lock);
if (--fp->f_count == 0)
{
pthread_mutex_unlock(fp->f_lock);
pthread_mutex_destroy(fp->f_lock);
free(fp);
}
else
{
pthread_mutex_unlock(fp->f_lock);
}
}