讨论一下关于 CRITICAL_SECTION 的两种用法

linsi 2016-11-02 02:38:04
非MFC程序,自己封装的一个临界区的类,用于线程间同步,现在有两种方法:

方法一:
class Lock
{
public:
void Lock() { EnterCriticalSection(&cs_); }
void UnLock() { LeaveCriticalSection(&cs_); }

private:
Lock() { InitializeCriticalSection(&cs); }
~Lock() { DeleteCriticalSection(&cs); }

CRITICAL_SECTION cs_;
}

方法二:
class Lock
{
public:
Lock(const CRITICAL_SECTION *cs):cs_(NULL) { cs_ = cs; }
void Lock() { EnterCriticalSection(cs_); }
void UnLock() { LeaveCriticalSection(cs_); }

private:
CRITICAL_SECTION *cs_;
}

这两种方法各有什么优点缺点? 大家一般使用哪种方法呢?或者有更好的方法?
...全文
694 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Saleayas 2016-11-04
  • 打赏
  • 举报
回复
你的第二个可以编译吗??
jiqiang01234 2016-11-04
  • 打赏
  • 举报
回复
引用 7 楼 linsi 的回复:
[quote=引用 6 楼 jiqiang01234 的回复:] 两种都不好。使用RAII来保证加锁和解锁的范围即可。另:等号重载也需要禁用

class Lock
{
public:
    Lock() { InitializeCriticalSection(&cs_); }
    ~Lock() { DeleteCriticalSection(&cs_); }
private:
     Lock(const Lock&);
     Lock& operator=(const Lock&);
private:
    CRITICAL_SECTION cs_;
}
可以这样使用(注意,需要大括号来保证作用域) { Lock lock; //保护的内容 ...... }
感谢回复~ 象第一种方式 RAII 有个问题吧,不能每次都用大括号来RAII吧,比如 在Read 的时候创建一个 Lock 对象,再在 Write 时又创建一个 Lock 对象,这两个对象不同,如何保证加锁效果? 你说的情况只能使用第二种方式加大括号来处理。创建时以调用类的 CRITICAL_SECTION 对象指针作为参数构造一个 Lock 对象,退出大括号时析构,这样可以达到目的。 使用 CRITICAL_SECTION 加锁方式,如果阻塞将从用户空间切换至内核,所以这种加锁方式比较费资源。 用哪种方式进行线程同步加锁较更方便和少耗资源呢? [/quote] 把第二种方法,改动一下
class Lock
{
public:
    explicit Lock(const CRITICAL_SECTION *cs):cs_(cs) { EnterCriticalSection(cs_); }
    ~Lock() {LeaveCriticalSection(cs_);}
private:
     Lock(const Lock&);
     Lock& operator=(const Lock&);    
private:
    CRITICAL_SECTION *cs_;
}
这样使用: CRITICAL_SECTION cs; void Read() { { Lock lock(&cs); //保护的代码 } } void Write() { { Lock lock(&cs); //保护的代码 } }
赵4老师 2016-11-04
  • 打赏
  • 举报
回复
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
jiqiang01234 2016-11-03
  • 打赏
  • 举报
回复
两种都不好。使用RAII来保证加锁和解锁的范围即可。另:等号重载也需要禁用

class Lock
{
public:
    Lock() { InitializeCriticalSection(&cs_); }
    ~Lock() { DeleteCriticalSection(&cs_); }
private:
     Lock(const Lock&);
     Lock& operator=(const Lock&);
private:
    CRITICAL_SECTION cs_;
}
可以这样使用(注意,需要大括号来保证作用域) { Lock lock; //保护的内容 ...... }
linsi 2016-11-03
  • 打赏
  • 举报
回复
引用 6 楼 jiqiang01234 的回复:
两种都不好。使用RAII来保证加锁和解锁的范围即可。另:等号重载也需要禁用

class Lock
{
public:
    Lock() { InitializeCriticalSection(&cs_); }
    ~Lock() { DeleteCriticalSection(&cs_); }
private:
     Lock(const Lock&);
     Lock& operator=(const Lock&);
private:
    CRITICAL_SECTION cs_;
}
可以这样使用(注意,需要大括号来保证作用域) { Lock lock; //保护的内容 ...... }
感谢回复~ 象第一种方式 RAII 有个问题吧,不能每次都用大括号来RAII吧,比如 在Read 的时候创建一个 Lock 对象,再在 Write 时又创建一个 Lock 对象,这两个对象不同,如何保证加锁效果? 你说的情况只能使用第二种方式加大括号来处理。创建时以调用类的 CRITICAL_SECTION 对象指针作为参数构造一个 Lock 对象,退出大括号时析构,这样可以达到目的。 使用 CRITICAL_SECTION 加锁方式,如果阻塞将从用户空间切换至内核,所以这种加锁方式比较费资源。 用哪种方式进行线程同步加锁较更方便和少耗资源呢?
赵4老师 2016-11-03
  • 打赏
  • 举报
回复
该看的书需要立即去看。
paschen 版主 2016-11-02
  • 打赏
  • 举报
回复
直接把对象封装在类中(而不是指针),产生异常等析构函数会自动释放资源,也即 :资源获取就是初始化(RAII)
linsi 2016-11-02
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
《Windows核心编程》
抱歉,这本书没看过,对这两种方法有解释吗?
引用 2 楼 wuleeemail 的回复:
方法1和方法2最大的不同是在1中将构造函数私有化了,那么关于构造函数私有化的用处或者好处,请你自己百度一下吧!
C++类的构造等基本方法和特性还是知道一些的,我想知道这两种方法的优缺点。你们一般用什么方法。
wuleeemail 2016-11-02
  • 打赏
  • 举报
回复
方法1和方法2最大的不同是在1中将构造函数私有化了,那么关于构造函数私有化的用处或者好处,请你自己百度一下吧!
赵4老师 2016-11-02
  • 打赏
  • 举报
回复
《Windows核心编程》

64,645

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧