Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7787785
  • 博文数量: 701
  • 博客积分: 2150
  • 博客等级: 上尉
  • 技术积分: 13233
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-29 16:28
个人简介

天行健,君子以自强不息!

文章分类

全部博文(701)

文章存档

2019年(2)

2018年(12)

2017年(76)

2016年(120)

2015年(178)

2014年(129)

2013年(123)

2012年(61)

分类: C/C++

2017-12-29 11:33:21

一、在多实例间实现全局的线程安全锁
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
阅读(1622) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~