最近在学习的过程中,遇到了多线程及互斥锁相关的问题,特写此文章以便日后参考。文章写作过程中参考了诸多网上大神的文章,在此不一一列出,如有雷同纯属巧合!
本文章的写作思路:首先给出测试代码,然后针对代码中使用的特别函数及知识点做额定说明。话不多说,测试代码如下:
//#互斥锁的测试
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
//创建互斥锁的全局变量
pthread_mutex_t myMutex1;
pthread_mutex_t myMutex2;
//全局变量
int iGlobalValue=0;
//初始化锁
int CreateMutexLock(pthread_mutex_t *mutex,pthread_mutexattr_t *attr)
{
int iReturnValue=-1;
//初始化成功返回0,否则返回非0
iReturnValue=pthread_mutex_init(mutex,attr);
return iReturnValue;
}
//加锁
int AddMutexLock(pthread_mutex_t *mutex)
{
int iReturnValue=-1;
iReturnValue=pthread_mutex_lock(mutex);
return iReturnValue;
}
//解锁
int UnlockMutexLock(pthread_mutex_t *mutex)
{
int iReturnValue=-1;
iReturnValue=pthread_mutex_unlock(mutex);
return iReturnValue;
}
//测试锁
void TestMutexLock(pthread_mutex_t *mutex)
{
int iReturnValue=-1;
iReturnValue=pthread_mutex_trylock(mutex);
if(0!=iReturnValue)
{
printf("This mutex lock is locked.\n");
}
else
{
printf("Try to add mutex lock success.\n");
}
}
//销毁锁
int DestoryMutexLock(pthread_mutex_t *mutex)
{
int iReturnValue=-1;
iReturnValue=pthread_mutex_destory(mutex);
return iReturnValue;
}
//测试函数1
void TestFunc1(void)
{
int i=0;
//初始化锁
if(0!=CreateMutexLock(&myMutex1,NULL))
{
printf("Create mutex lock fail.\n");
return;
}
//加锁
if(0!=AddMutexLock(&myMutex1))
{
printf("Add mutex lock fail.\n");
return;
}
for(i=0;i<20;i++)
{
//访问全局变量 iiGlobalValue
printf("This is TestFunc1() and global number value is:%d.\n",iGlobalValue++);
sleep(1);
}
//解锁
if(0!=UnlockMutexLock(&myMutex1))
{
printf("Unlock mutex lock fail.\n");
return;
}
//销毁锁
if(0!=DestoryMutexLock(&myMutex1))
{
printf("Destory mutex lock fail.\n");
return;
}
//线程自身调用pthread_exit()函数,终止线程
pthread_exit(0);
}
//测试函数2
void TestFunc2(void)
{
int i=0;
//初始化锁
if(0!=CreateMutexLock(&myMutex2,NULL))
{
printf("Create mutex lock fail.\n");
return;
}
//加锁
TestMutexLock(&myMutex2);
for(i=0;i<20;i++)
{
//访问全局变量 iiGlobalValue
printf("This is TestFunc2() and global number value is:%d.\n",iGlobalValue++);
sleep(1);
}
//解锁
if(0!=UnlockMutexLock(&myMutex2))
{
printf("Unlock mutex lock fail.\n");
return;
}
//销毁锁
if(0!=DestoryMutexLock(&myMutex2))
{
printf("Destory mutex lock fail.\n");
return;
}
//线程自身调用pthread_exit()函数,终止线程
pthread_exit(0);
}
int main(int argc,char *argv[])
{
//创建线程ID
pthread_t threadID1;
pthread_t threadID2;
//创建线程1
if(0!=pthread_create(&threadID1,NULL,(void*)TestFunc1,NULL))
{
printf("Create thread fail.\n");
return -1;
}
//创建线程2
if(0!=pthread_create(&threadID2,NULL,(void*)TestFunc2,NULL))
{
printf("Create thread fail.\n");
return -1;
}
//等待线程结束,主线程调用pthread_join()函数,结束ID号对应的线程
pthread_join(threadID1,NULL);
pthread_join(threadID2,NULL);
return 0;
}
1.1.创建线程ID时,需要使用pthread_t标识符,其在头文件/usr/include/bits/pthreadtypes.h中定义:
typedef unsigned long int pthread_t;
1.2 创建新线程的函数:pthread_create(),该函数的原型为:
int pthread_create(pthread_t *threadID,pthread_attr_t *attr,void* (*start_routine)(void*),void *arg);
参数threadID:线程标识符
参数attr:线程属性设置
参数start_routine:线程函数的起始地址
参数arg:传递给start_routine()的参数
创建线程成功返回0,否则返回非零值。
1.3线程结束的方式:
(1)线程被其他线程调用pthread_join()函数而终止
pthread_join()函数的原型为:void pthread_join(pthread_t pID,void ** thread_return);
第一个参数:线程标识符,第二个参数用户定义的指针,用来存储被等待线程的返回值。调用此函数的函数将一直等待被等待的线程结束后,才会继续执行。一个线程不能同时被多个其他线程等待,如果有多个线程同时等待一个线程,则第一个等待的线程可成功返回,其他线程将返回error。值的注意的是,如果在主线程中不适用此函数,则创建的其他子线程可能还没来得及执行时,主线程就已经结束。而调用此函数后,主线程会等待其他子线程执行完毕且返回后才继续执行主线程的功能。
(2)线程自身调用pthread_exit()函数而终止
pthread_exit()函数的原型为:void pthread_exit(void *retval);
2.1创建互斥锁变量使用:pthread_mutex_t,其定义位于<pthread.h>中
2.2初始化互斥锁有两种方式:
(1)静态方式
使用宏PTHREAD_MUTEX_INITIALIZER,例如 pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
(2)动态方式
使用pthread_mutex_init()函数,具体例子见上述代码。
pthread_mutex_init()函数的原型声明:
int pthread_mutex_init(pthread_mutex_t *thread_Mutex,const pthread_mutexattr_t *attr);
第一个参数是:互斥锁变量,第二个参数是互斥锁属性
函数初始化互斥锁成功返回0,否则返回非0。
2.3加互斥锁
使用int pthread_mutex_lock(pthread_mutex_t *mutex);
函数调用成功返回0,否则返回非0。
2.4解互斥锁
使用int pthread_mutex_unlock(pthread_mutex_t *mutex);
函数调用成功返回0,否则返回非0。注意,不能对一个互斥锁进行多次重复解锁操作。
2.5销毁互斥锁
使用int pthread_mutex_destroy(pthread_mutex_t *mutex);
函数调用成功返回0,否则返回非0。注意,如果想对互斥锁进行销毁操作,必须确保该互斥锁处于未上锁(解锁)状态,尝试对上锁的互斥锁进行销毁锁操作将导致错误。
2.6测试互斥锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);
函数调用成功返回0,否则返回非0。对于未上锁的互斥锁进行测试则返回0,同时将未加锁的互斥锁加锁。对于已经加锁的互斥锁进行测试后,函数会返回EBUSY。
备注:上述针对互斥锁使用的函数,可能过于简单,如需详细信息可参考<pthread.h>中的定义或其他资料。