先进两次临界区再退两次,行不行

samuelo 2010-02-09 02:46:15
有线程A、B,都会使用一个对象C。
C有自己的临界区。
class C
{
public:
void Set( int Num );
{

EnterCriticalSection(&m_cs);

//第二次进入临界区,之前未退出
EnterCriticalSection(&m_cs);

m_nNum = nNum;

LeaveCriticalSection(&m_cs);

LeaveCriticalSection(&m_cs);
}

private:
int m_nNum;
};


这么写会不会有问题?
...全文
222 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
mmlii 2011-07-26
  • 打赏
  • 举报
回复
可以多次进入,但只能退出一次。
因为进入时当前线程是否已经拥有了临界区所有权,如果没有,则等待,否则继续;
而离开时如果当前线程没有所有权,则会引发错误,会导致其他线程无法进入临界区!见MSN:

If a thread calls LeaveCriticalSection when it does not have ownership of the specified critical section object, an error occurs that may cause another thread using EnterCriticalSection to wait indefinitely.

http://msdn.microsoft.com/zh-cn/library/ms886733.aspx

Tomsdinary 2010-06-11
  • 打赏
  • 举报
回复
同一个线程多次进入一个临界区是有意义的。比如类A,你用一个对象级的锁把它的每个成员函数都做成线程安全的,此时在一个成员函数里可能希望调用另一个成员函数。如果不允许重入,那么就需要显式地指出该函数是否需要加锁,这是很不友好的。这会对接口设计产生不好的影响。
dengsf 2010-02-09
  • 打赏
  • 举报
回复
可以的,
CRITICAL_SECTION是“可重入的”,
也就是如果当前线程已经EnterCriticalSection,
同线程内执行的其它EnterCriticalSection也成功,
不过要注意Leave跟Enter的次数必须一样,当前线程才算真正Leave
samuelo 2010-02-09
  • 打赏
  • 举报
回复
13楼,我会分点分给你的。
我想再讨论讨论。
结帖后恐怕没人看了。
tubo_true 2010-02-09
  • 打赏
  • 举报
回复
引用楼主 samuelo 的回复:
有线程A、B,都会使用一个对象C。
C有自己的临界区。
class C
{
public:
  void Set( int Num );
  {

EnterCriticalSection(&m_cs);

        //第二次进入临界区,之前未退出
EnterCriticalSection(&m_cs);

m_nNum = nNum;

LeaveCriticalSection(&m_cs);

LeaveCriticalSection(&m_cs);
    }

private:
    int m_nNum;
};


这么写会不会有问题?


肯定会有,原因大家都说了,我就不说了
zhou1xp 2010-02-09
  • 打赏
  • 举报
回复
楼主结帖吧,我只差1分就四个内裤了,明天放假,我希望今天升到四个裤裤
WizardK 2010-02-09
  • 打赏
  • 举报
回复
引用 11 楼 samuelo 的回复:
其实我和5楼 zhou1xp 的看法差不多。但有人说会出错。所以来问问。


一般意义上讲,你用InitializeCriticalSection初始化的临界区,线程间可同时进入一次退出一次。
你用InitializeCriticalSectionAndSpinCount或者InitializeCriticalSection+SetCriticalSectionSpinCount初始化的临界区,可以看作线程间可同时进入多次退出多次。

但到了一个线程内部,多次进入的问题,实践证明可以多次进入,但第一次进入后,其后的进入没有产生任何影响,也没有意义。
samuelo 2010-02-09
  • 打赏
  • 举报
回复
其实我和5楼 zhou1xp 的看法差不多。但有人说会出错。所以来问问。
WizardK 2010-02-09
  • 打赏
  • 举报
回复
引用 4 楼 samuelo 的回复:
2楼:
临界区初始化了。代码里省略。

1楼、3楼:
你们在临界区依赖线程所有权还是依赖加锁个数上理解不同。
这正是我疑惑的地方,发贴的原因。


一个线程内部,多次进入一个临界区是可以的,最后只需要退出一次就可,但这是没有任何意义的。
zhou1xp 2010-02-09
  • 打赏
  • 举报
回复
说程序会挂的请去看下原子操作
zhou1xp 2010-02-09
  • 打赏
  • 举报
回复
进入了临界区,你后面的EnterCriticalSection(&m_cs); 程序就会挂在这里,后面就永远不可能再执行了

请看清楚,它不是不同的线程,他是一个线程,我前几天看核心编程绝对说过是可以这样的,只不过是一般没人会这么用
jx1j1x 2010-02-09
  • 打赏
  • 举报
回复
引用 5 楼 zhou1xp 的回复:
其实你说的加两次锁的问题是可以的,我最近看Windows核心编程里面说过这种情形,要求注意的是不用这个锁的时候一定要delete,不然会出现问题

不要误导。。。。
楼主临界区的概念知道吗?EnterCriticalSection(&m_cs);
进入了临界区,你后面的EnterCriticalSection(&m_cs); 程序就会挂在这里,后面就永远不可能再执行了。
如果楼主两个线程用的是c的两个不同的对象还是同一个对象,那么,这两个线程都会挂住。
搞不懂你这有什么意义。
WizardK 2010-02-09
  • 打赏
  • 举报
回复
引用 4 楼 samuelo 的回复:
2楼:
临界区初始化了。代码里省略。

1楼、3楼:
你们在临界区依赖线程所有权还是依赖加锁个数上理解不同。
这正是我疑惑的地方,发贴的原因。


把临界区理解为最大值和初始值为1的信号量即可
zhou1xp 2010-02-09
  • 打赏
  • 举报
回复
其实你说的加两次锁的问题是可以的,我最近看Windows核心编程里面说过这种情形,要求注意的是不用这个锁的时候一定要delete,不然会出现问题
samuelo 2010-02-09
  • 打赏
  • 举报
回复
2楼:
临界区初始化了。代码里省略。

1楼、3楼:
你们在临界区依赖线程所有权还是依赖加锁个数上理解不同。
这正是我疑惑的地方,发贴的原因。
WizardK 2010-02-09
  • 打赏
  • 举报
回复
不行
你没有理解临界区的意思,举个例子,桌子只有一个苹果,你拿走了,你想再拿走一个,然后还两个,可是等你想拿第二个的时候,你会发现桌子上没有苹果了,你就死等在这里了。。。
zhou1xp 2010-02-09
  • 打赏
  • 举报
回复
还有你的临界区变量没有初始化,第一次退出的时候可能产生不可预料的错误
踏实每一步 2010-02-09
  • 打赏
  • 举报
回复
EnterCriticalSection Function

Waits for ownership of the specified critical section object. The function returns when the calling thread is granted ownership

void Set( int Num );
{

EnterCriticalSection(&m_cs); // 如果有其他线程在调用此线程,此线程就停在这里了,下面那句相同的还有什么用。如果其他线程没调用,在同一线程里锁两边跟锁一边有什么区别,代码很少会写成这样

//第二次进入临界区,之前未退出
EnterCriticalSection(&m_cs);

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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