一、在多实例间实现全局的线程安全锁
1.1 实例场景:
1. 类的声明与定义
//channel.h
class CChannel{
friend void* audio_write_process(void* params);
friend void* video_write_process(void* params);
public:
CChannel();
~CChannel();
public:
int handle_audio_thread();
int handle_video_thread();
private:
pthread_t _audio_write_thread_id;
pthread_t _video_write_thread_id;
private:
static pthread_mutex_t _avfile_lock; // 声明一个静态成员变量
}
// channel.cpp
#include "channel.h"
/** 以静态方式初始化锁 */
pthread_mutex_t CChannel::_avfile_lock = PTHREAD_MUTEX_INITIALZER;
void* audio_write_process(void* params){
CChannel* pchannel = (CChannel*)params;
pchannel->handle_audio_thread();
return NULL;
}
void* video_write_process(void* params){
CChannel* pchannel = (CChannel*)params;
pchannel->handle_video_thread();
return NULL;
}
CChannel::CChannel(){
...
}
CChannel::~CChanel(){
...
}
CChannel::handle_audio_thread(){
...
pthread_mutex_lock(&_avfile_lock);
// 需要以独占的方式打开该文件,写入信息,并关闭
open_file(output.mp4);
write_file("...", output.mp4);
close_file(output.mp4);
pthread_mutex_unlock(&_avfile_lock);
...
}
CChannel::handle_video_thread(){
...
pthread_mutex_lock(&_avfile_lock);
// 需要以独占的方式打开该文件,写入信息,并关闭
open_file(output.mp4);
write_file("...", output.mp4);
close_file(output.mp4);
pthread_mutex_unlock(&_avfile_lock);
...
}
CChannel::init(){
pthread(&_audio_write_thread_id, NULL, audio_write_process, this);
pthread(&_video_write_thread_id, NULL, video_write_process, this);
}
// main.cpp
#include "channel.h"
int main(){
CChannel *pchannel_first = new CChannel();
pchnnel_first->init();
CChannel *pchannel_second = new CChannel();
pchnnel_second->init();
}
1.2 原理解析:
这里主要应用的是类的静态成员变量;
使用类的静态成员变量:
#include
class Point
{
public:
Point()
{
m_nPointCount++;
}
~Point()
{
m_nPointCount--;
}
static void output()
{
printf("%d\n", m_nPointCount);
}
private:
static int m_nPointCount;
};
void main()
{
Point pt;
pt.output();
}
按Ctrl+F7编译无错误,按F7生成EXE程序时报链接错误
error LNK2001: unresolved external symbol "private: static int Point::m_nPointCount" (?m_nPointCount@Point@@0HA)
这是因为类的静态成员变量在使用前必须先初始化。
在main()函数前加上int Point::m_nPointCount = 0;
再编译链接无错误,运行程序将输出1。
结论5:类的静态成员变量必须先初始化再使用。
结合上面的五个例子,对类的静态成员变量和成员函数作个总结:
1)、静态成员函数中不能调用非静态成员。
2)、非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,
所以在非静态成员函数中是可以调用静态成员的。
3)、静态成员变量使用前必须先初始化(如int MyClass::m_nNumber = 0;),否则会在linker时出错。
再给一个利用类的静态成员变量和函数的例子以加深理解,
这个例子建立一个学生类,每个学生类的对象将组成一个双向链表,用一个静态成员变量记录这个双向链表的表头,
一个静态成员函数输出这个双向链表。
#include
#include
const int MAX_NAME_SIZE = 30;
class Student
{
public:
Student(char *pszName);
~Student();
public:
static void PrintfAllStudents();
private:
char m_name[MAX_NAME_SIZE];
Student *next;
Student *prev;
static Student *m_head;
};
Student::Student(char *pszName)
{
strcpy(this->m_name, pszName);
//建立双向链表,新数据从链表头部插入。
this->next = m_head;
this->prev = NULL;
if (m_head != NULL)
m_head->prev = this;
m_head = this;
}
Student::~Student ()//析构过程就是节点的脱离过程
{
if (this == m_head) //该节点就是头节点。
{
m_head = this->next;
}
else
{
this->prev->next = this->next;
this->next->prev = this->prev;
}
}
void Student::PrintfAllStudents()
{
for (Student *p = m_head; p != NULL; p = p->next)
printf("%s\n", p->m_name);
}
Student* Student::m_head = NULL;
void main()
{
Student studentA("AAA");
Student studentB("BBB");
Student studentC("CCC");
Student studentD("DDD");
Student student("MoreWindows");
Student::PrintfAllStudents();
}
程序将输出:
MoreWindows
DDD
CCC
BBB
AAA
Press any key to continue
参考:
http://blog.csdn.net/morewindows/article/details/6721430
阅读(1668) | 评论(0) | 转发(0) |