线程锁的基本概念与简单封装
1.在多线程环境中,当我们需要保持线程同步时,通常通过锁来实现。
互斥锁的使用过程中,主要有第一:线程锁的初始化,pthread_mutex_init
第二:线程锁的释放,pthread_mutex_destory
第三:线程锁的加锁操作,pthread_mutex_lock
第四:线程锁的解锁操作,pthread_mutex_unlock
2.锁的初始化
我们可以采用静态或者动态的方法创建锁锁。
第一:静态创建,无需释放操作
可以用宏PTHREAD_MUTEX_INITIALIZER来静态的初始化锁,互斥锁是pthread_mutex_t的结构体,
而这个宏是一个结构常量,如下可以完成静态的初始化锁:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
第二:动态创建,需要释放操作
(1) 初始化函数, pthread_mutex_init原函数类型如下:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr)
具体操作为:
pthread_mutex_t m_Mutex = PTHREAD_MUTEX_INITIALIZER;
(2) 释放函数 pthread_mutex_destory可以释放锁占用的资源,但这有一个前提上锁当前是没有被锁的状态。
原函数类型如下:
int pthread_mutex_destroy(pthread_mutex_t *mutex)
mutex 指向要销毁的互斥锁的指针,互斥锁销毁函数在执行成功后返回 0,否则返回错误码。
具体操作为:
pthread_mutex_init(&mutex,NULL);
pthread_mutex_destroy(&mutex);
3.加锁与解锁
pthread_mutex_trylock()为尝试锁,如果已经加锁则直接返回EBUSY,而pthread_mutex_lock(),则是挂起等待。
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
4.线程锁的简单封装
思路:
互斥器放在类外,外部初始化互斥器,然后传进互斥器(第一、二种方法)
互斥器放在类内,内部直接初始化互斥器,然后使用互斥器(第三种方法)
/*
* Lock.h
*/
#ifndef LOCK_H_
#define LOCK_H_
#include <pthread.h>
class Lock
{
public:
Lock(pthread_mutex_t* m_Mutex);
~Lock();
void mutexLock();
void mutexUnlock();
private:
pthread_mutex_t* m_Mutex;
};
#endif //LOCK_H_
/*
* Lock.cpp
*/
#include "Lock.h"
#include <stdio.h>
#include <errno.h>
Lock::Lock(pthread_mutex_t* m_Mutex):m_Mutex(m_Mutex)
{
mutexLock();
}
Lock::~Lock()
{
mutexUnlock();
}
void Lock::mutexLock()
{
//非空,则进行加锁操作,关于指针,每次操作前最好确定进行非空判断,保证程序不会中断
if(this->m_Mutex)
{
pthread_mutex_lock(this->m_Mutex);
}
}
void Lock::mutexUnlock()
{
//非空,则进行解锁锁操作,关于指针,每次操作前最好确定进行非空判断,保证程序不会中断
if(this->m_Mutex)
{
pthread_mutex_unlock(this->m_Mutex);
}
}
/*
* main.cpp
*/
#include <stdio.h>
#include <memory>
#include <string>
#include "Lock.h"
pthread_mutex_t m_Mutex = PTHREAD_MUTEX_INITIALIZER; //静态初始化,类外初始化
void *testMsg(void *testMsg)
{
char *msg = (char *)testMsg;
Lock test_lock(&m_Mutex); //创建锁对象时,需要把互斥器传进去,进行资源管理,无需手动解锁,过了作用域自动解锁
for(int i=0; i< 5; i++ )
{
printf("testMsg(%d): %s\n", i+1, msg);
sleep(1);
}
return NULL;
}
int main()
{
pthread_t test1,test2;
//创建两个工作线程
pthread_create( &test1, NULL, &testMsg, (void *)"First thread");
pthread_create( &test2, NULL, &testMsg, (void *)"Second thread");
//等待线程结束
pthread_join( test1, NULL);
pthread_join( test2, NULL);
return 0;
}
/*
* Makefile
*/
main:Lock.o main.o
g++ main.o Lock.o -L/usr/lib64/ -lcurl -o main
Lock.o:Lock.cpp
g++ -c Lock.cpp -o Lock.o -I/usr/include/
main.o:main.cpp
g++ -c main.cpp -o main.o -I/usr/include/
结果:顺序输出
testMsg(1): Second thread
testMsg(2): Second thread
testMsg(3): Second thread
testMsg(4): Second thread
testMsg(5): Second thread
testMsg(1): First thread
testMsg(2): First thread
testMsg(3): First thread
testMsg(4): First thread
testMsg(5): First thread
(2) 第二种,静态初始化,只进行简单封装, 没有进行资源管理
/*
* Lock.h
*/
#ifndef LOCK_H_
#define LOCK_H_
#include <pthread.h>
class Lock
{
public:
Lock(pthread_mutex_t* m_Mutex);
~Lock();
int mutexLock();
int mutexUnlock();
private:
pthread_mutex_t* m_Mutex;
};
#endif //LOCK_H_
/*
* Lock.cpp
*/
#include "Lock.h"
#include <stdio.h>
#include <errno.h>
Lock::Lock(pthread_mutex_t* m_Mutex):m_Mutex(m_Mutex)
{
}
Lock::~Lock()
{
}
int Lock::mutexLock()
{
if(this->m_Mutex)
{
pthread_mutex_lock(this->m_Mutex);
}
}
int Lock::mutexUnlock()
{
if(this->m_Mutex)
{
pthread_mutex_unlock(this->m_Mutex);
}
}
/*
* main.cpp
*/
#include <stdio.h>
#include <memory>
#include <string>
#include "Lock.h"
pthread_mutex_t g_Mutex = PTHREAD_MUTEX_INITIALIZER; //静态初始化
Lock test_lock(&g_Mutex); //创建锁对象
void *testMsg(void *testMsg)
{
char *msg = (char *)testMsg;
test_lock.mutexLock(); //加锁,需手动解锁
for(int i=0; i< 5; i++ )
{
printf("testMsg(%d): %s\n", i+1 ,msg);
sleep( 1 );
}
test_lock.mutexUnlock(); //解锁
return NULL;
}
int main()
{
pthread_t test1,test2;
//创建两个工作线程
pthread_create( &test1, NULL, &testMsg, (void *)"First thread" );
pthread_create( &test2, NULL, &testMsg, (void *)"Second thread" );
//等待线程结束
pthread_join( test1, NULL);
pthread_join( test2, NULL);
return 0;
}
/*
* Makefile
*/
main:Lock.o main.o
g++ main.o Lock.o -L/usr/lib64/ -lcurl -o main
Lock.o:Lock.cpp
g++ -c Lock.cpp -o Lock.o -I/usr/include/
main.o:main.cpp
g++ -c main.cpp -o main.o -I/usr/include/
结果:顺序输出
testMsg(1): Second thread
testMsg(2): Second thread
testMsg(3): Second thread
testMsg(4): Second thread
testMsg(5): Second thread
testMsg(1): First thread
testMsg(2): First thread
testMsg(3): First thread
testMsg(4): First thread
testMsg(5): First thread
(3) 第三种,动态初始化,只进行简单封装,没有进行资源管理
/*
* Lock.h
*/
#ifndef LOCK_H_
#define LOCK_H_
#include <pthread.h>
class Lock
{
public:
Lock();
~Lock();
int mutexLock();
int mutexUnlock();
private:
void mutexInit();
void mutexDestroy();
private:
pthread_mutex_t m_Mutex;
};
#endif //LOCK_H_
/*
* Lock.cpp
*/
#include "Lock.h"
#include <stdio.h>
#include <errno.h>
Lock::Lock()
{
mutexInit();
}
Lock::~Lock()
{
mutexDestroy();
}
void Lock::mutexInit()
{
pthread_mutex_init(&m_Mutex, NULL);
}
int Lock::mutexLock()
{
pthread_mutex_lock(&m_Mutex);
}
int Lock::mutexUnlock()
{
pthread_mutex_unlock(&m_Mutex);
}
void Lock::mutexDestroy()
{
pthread_mutex_destroy(&m_Mutex);
}
/*
* main.cpp
*/
#include <stdio.h>
#include <memory>
#include <string>
#include "Lock.h"
Lock g_Mutex; //创建锁对象,内部初始化互斥器
void *testMsg(void *testMsg)
{
char *msg = (char *)testMsg;
g_Mutex.mutexLock(); //加锁
for(int i=0; i< 5; i++ )
{
printf("testMsg(%d):%s\n", i+1, msg);
sleep( 1 );
}
g_Mutex.mutexUnlock(); //解锁
return NULL;
}
int main()
{
pthread_t test1,test2;
//创建两个工作线程
pthread_create( &test1, NULL, &testMsg, (void *)"First thread" );
pthread_create( &test2, NULL, &testMsg, (void *)"Second thread" );
//等待线程结束
pthread_join( test1, NULL);
pthread_join( test2, NULL);
return 0;
}
/*
* Makefile
*/
main:Lock.o main.o
g++ main.o Lock.o -L/usr/lib64/ -lcurl -o main
Lock.o:Lock.cpp
g++ -c Lock.cpp -o Lock.o -I/usr/include/
main.o:main.cpp
g++ -c main.cpp -o main.o -I/usr/include/
结果:顺序输出
testMsg(1): Second thread
testMsg(2): Second thread
testMsg(3): Second thread
testMsg(4): Second thread
testMsg(5): Second thread
testMsg(1): First thread
testMsg(2): First thread
testMsg(3): First thread
testMsg(4): First thread
testMsg(5): First thread