【发布时间】:2014-03-08 21:04:11
【问题描述】:
当您有一个包含临界区 CS 和指向另一个对象 OBJ2 的指针的对象 OBJ1 时,我无法弄清楚正确的关闭过程是什么
假设你有两个函数 A 和 B。
A进入临界区,修改OBJ2中的数据,离开临界区。 B 是一个关闭/销毁程序,应该销毁所有东西(OBJ2、CS 和 OBJ1)
我的问题是:
您如何解决由于 B 已经进入临界区而导致 A 等待进入临界区的场景? B会摧毁一切。如果“破坏”(出于某种有趣的原因)导致/允许 A 进入临界区,则 A 将生成异常,因为它正在尝试访问不再存在的对象。如果“破坏”没有导致 A 进入临界区,那么 A 将永远挂起等待进入临界区。
销毁包含临界区和指向对象的指针的类实例的正确方法是什么?
对我来说,似乎唯一的解决方案是将关键部分作为全局变量,而数据可以放在“类”(结构)中......但我不喜欢那个解决方案!
我使用的语言是 C。我知道 C 中没有类。我有结构的实例。
例子:
typedef struct classX_t
{
CRITICAL_SECTION cs;
classY* thisY;
} classX;
typedef struct classY_t
{
int some_variable;
} classY;
我创建了一个 X 的实例和一个 Y 的实例。变量 'thisY' 指向 Y 的实例。我的两个函数是:
void funcA(classX* thisClassX)
{
if (thisClassX == NULL) return;
EnterCriticalSection(thisClassX->cs);
thisClassX->thisY->some_variable++;
LeaveCriticalSection(thisClass->cs);
}
void funcB(classX* thisClassX)
{
if (thisClassX == NULL) return;
EnterCriticalSection(thisClassX->cs);
/* free stuff here */
free(thisClassX->thisY);
DeleteCriticalSection(thisClass->cs);
/* and destroy instance */
free(thisClassX)
}
如果 funcA 正在等待进入临界区,因为 B 已经进入了临界区,那么我看不出 funcA 如何正确执行而不会导致问题。有什么办法解决这个问题?
编辑:
也许我需要某种“锁定”计数;即当某些代码进入临界区时计数器增加 1 并在代码离开临界区时递减?如果我有,那么关闭程序可以检查计数以查看它是否大于 1(表明其他一些代码正在等待进入临界区),如果计数大于 1,那么它可以休眠直到计数消失回到 1。所以这就是我的建议:
每个函数都这样做:
void someFunction(...)
{
if (thisClassX == NULL) return;
thisClassX->counter++;
EnterCriticalSection(thisClassX->cs);
/* do something */
LeaveCriticalSection(thisClassX->cs);
thisClassX->counter--;
}
【问题讨论】:
-
"...销毁一个类的实例..." 那么,这不是一个C语言问题吗?
-
正如 WhozCraig 所说,您能否说得更具体一些,因为目前还不太清楚您在说什么,而且剪掉的一些代码也会很棒
-
这是一个很常见的问题,你想到了一切,却忽略了程序关闭。没有神奇的解决方案,而且通常很难解决,因为退出请求是如此完全异步。除了出口(0); C++11 中也包含 std::quick_exit()
-
我已经编辑了我的问题
-
其实有一个神奇的解决方案。只需按照您喜欢的任何顺序删除 B 中的所有内容。原因很明显:除非调用 B 的线程是唯一运行的线程(或唯一运行的可能调用 A 的线程),否则不可能以安全的方式执行此操作。这意味着您必须已经退出所有其他线程,因此没有必要同步任何内容。如果有其他线程正在运行(可能调用 A),则对象是否通过 CS“安全”访问和删除并不重要。这将导致访问 invalid 对象。
标签: c windows multithreading mutex critical-section