[英]Why should Next() operation of a singly linked list be protected with a critical section?
我正在阅读Win32中的《 多线程应用程序 》一书
该书说, return node->next
将被编译成单独的机器指令,这些指令不会作为原子操作执行,因此Next()
也应由关键部分保护。
我的问题是,它会被翻译成什么指令以引起比赛状况?
typedef struct _Node
{
struct Node *next;
int data;
} Node;
typedef struct _List
{
Node *head;
CRITICAL SECTION critical_sec;
} List;
List *CreateList()
{
List *pList = malloc(sizeof(List));
pList->head = NULL;
InitializeCriticalSection(&pList->critical_sec);
return pList;
}
void DeleteList(List *pList)
{
DeleteCriticalSection(&pList->critical_sec);
free(pList);
}
void AddHead(List *pList, Node *node)
{
EnterCriticalSection(&pList->critical_sec);
node->next = pList->head;
pList->head = node;
LeaveCriticalSection(&pList->critical_sec);
}
void Insert(List *pList, Node *afterNode, Node *newNode)
{
EnterCriticalSection(&pList->critical_sec);
if (afterNode == NULL)
{
AddHead(pList, newNode);
}
else
{
newNode->next = afterNode->next;
afterNode->next = newNode;
}
LeaveCriticalSection(&pList->critical_sec);
}
Node *Next(List *pList, Node *node)
{
Node* next;
EnterCriticalSection(&pList->critical_sec);
next = node->next;
LeaveCriticalSection(&pList->critical_sec);
return next;
}
编辑:
好的,尽管在这种特殊情况下它不会破坏单个链表而不保护Next()
操作,但是共享结构应该整体上受到保护,或者一无所获。
return node->next
执行两项操作; 它首先将node
指向的struct
加载到内存中,然后查看node+offsetof(next)
以查找next
指针,将其加载到寄存器中,然后返回到调用程序。 同时, node
的内容可能会被另一个执行线程操纵。
...但是...
“作家”(如添加或删除节点) 必须互斥。 关键部分是一个不错的选择。
“读者”(例如“下一个”)可以彼此并发运行。
建议:
如果可以使用Windows Vista或更高版本,请考虑使用SRW锁:
虽然我认为sarnold的答案是正确的,但我只是想指出,CreateList中malloc()调用中的sizeof()调用似乎有一个错误。 我相信它应该是:
List *pList = malloc(sizeof(List));
按照这种方式,您将创建足够的内存来保存指向 List而不是List结构的指针 。 (您可能还希望将返回类型强制转换为(List *)并将其与NULL比较,然后再使用。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.