比如下面一个例子:两个线程同时对一个变量操作(假如对一个变量i进行加1),有可能就会出现数据混乱(即每线程对i+1但是结果不是真正的结果),注意:线程是并发的,出现这种情况很正常。下面写个例子演示一下。
#include
#include
#include
#define NLOOP 5000 //这里我让每个线程加5000次
int counter; //定义一个全局变量来让线程自加
//线程执行函数
void *fun(void *arg)
{
int i = 0;
int val = 0;
int ID = 0;
ID = (int)arg;
//每个线程加个5000次
for (i = 0; i < NLOOP; i++)
{
val = counter;
printf("我是第%d个线程: %d\n", ID+1, val + 1);
counter = val + 1;
}
return NULL;
}
int main(void)
{
//建立两个线程ID
pthread_t tidA, tidB;
//创建线程,让这两个线程执行fun函数
pthread_create(&tidA, NULL, &fun, NULL);
pthread_create(&tidB, NULL, &fun, NULL);
//回收进程
pthread_join(tidA, NULL);
pthread_join(tidB, NULL);
return 0;
}
当我们把这段函数放到虚拟机中运行,最后的结果就可能会是10000的结果,或者少于10000 的结果,但是,按照正常来说应该要是10000,而少于10000的结果就是数据混乱的结果。
注意:编译这个文件的时候要加上-lpthread,比如gcc test.c -o test -lpthread
互斥锁我们可以想象成在超市的保险柜(进商场前存放东西的柜子)。然后把线程比喻成一个人,你进超市的时候,你就要先找到没有锁住的柜子,把柜子锁住(表示你正在使用),这样其他的人(其他的线程)就无法再使用这个柜子了,如果想要使用该柜子就需要你解锁,别人才可以使用。
保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共 享资源进行访问。如果有多个线程试图同时访问临界区,那么 在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释 放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。(你可以这么认为,这临界区就是我上面说的柜子)。
注意:这个临界区要尽可能的小!太大会影响程序的性能!
注意:常用的就是默认属性,就是pthread_mutex_init函数的第二个参数传NULL
产生原因
在下面两个示例代码中,C文件建立静态互斥锁,C++那份代码采用动态建立互斥锁。
#include
#include
#include
#define NLOOP 5000 //用于每个线程加5000次
int counter; //建立一个全局变量给线程操作
//设计一个全局的锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *doit(void *vptr)
{
int i, val;
//谁要操作全局资源,谁拿锁
for (i = 0; i < NLOOP; i++)
{
//拿锁
pthread_mutex_lock(&mutex);
//直到解锁,都是临界区
val = counter;
printf("%x: %d\n", (unsigned int)pthread_self(), val + 1);
counter = val + 1;
//解锁
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void)
{
pthread_t tidA, tidB;
//建立线程
pthread_create(&tidA, NULL, &doit, NULL);
pthread_create(&tidB, NULL, &doit, NULL);
//回收线程
pthread_join(tidA, NULL);
pthread_join(tidB, NULL);
return 0;
}
头文件
#ifndef BASETHRED_MUTEX_H
#define BASETHRED_MUTEX_H
#include
#include
#include
class CBaseThread_mutex
{
public:
CBaseThread_mutex();
~CBaseThread_mutex();
bool lock(); //加锁
bool unlock(); //解锁
bool trylock(); //尝试加锁
protected:
pthread_mutex_t m_mutex; //互斥锁
}
#define endif
cpp文件
#include "CBase_pthread_mutex.h"
//构造函数建立互斥锁
CBaseThread_mutex::CBaseThread_mutex()
{
//互斥量的初始化
if(pthread_mutex_init(&m_mutex,NULL)!=0)
{
perror("mutex_init error:");
}
}
//析构函数销毁互斥锁
CBaseThread_mutex::~CBaseThread_mutex()
{
//互斥量的销毁
if(pthread_mutex_destroy(&m_mutex)!=0)
{
perror("mutex_destroy error:");
}
}
//拿锁函数
bool CBaseThread_mutex::lock()
{
int ret = pthread_mutex_lock(&m_mutex);
if(ret != 0)
{
perror("mutex_lock error:");
}
return ret ==0 ? true:false
}
//解锁函数
bool CBaseThread_mutex::unlock()
{
int ret = pthread_mutex_unlock(&m_mutex);
if(ret != 0)
{
perror("mutex_unlock error:");
}
return ret ==0 ? true:false
}
//试图拿锁函数
bool CBaseThread_mutex::trylock()
{
int ret = pthread_mutex_trylock(&m_mutex);
if(ret != 0)
{
perror("mutex_lock error:");
}
return ret ==0 ? true:false
}