[英]Why should Next() operation of a singly linked list be protected with a critical section?
I'm reading the book Multithreading Applications in Win32 我正在阅读Win32中的《 多线程应用程序 》一书
The book says return node->next
will be compiled into separate machine instructions that would not be executed as an atomic operation, so Next()
should also be protected by the critical section. 该书说,
return node->next
将被编译成单独的机器指令,这些指令不会作为原子操作执行,因此Next()
也应由关键部分保护。
My question is, what instructions could it be translated into, to cause a race condition? 我的问题是,它会被翻译成什么指令以引起比赛状况?
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;
}
Edit: 编辑:
OK, although in this particular case it won't corrupt the singly linked list w/o protecting the Next()
operation, a shared structure should be protected as a whole or nothing, generally. 好的,尽管在这种特殊情况下它不会破坏单个链表而不保护
Next()
操作,但是共享结构应该整体上受到保护,或者一无所获。
return node->next
performs two operations; return node->next
执行两项操作; it first loads the struct
pointed to by node
into memory, then looks at the node+offsetof(next)
to find the pointer next
, load that into a register, and then return to the calling program. 它首先将
node
指向的struct
加载到内存中,然后查看node+offsetof(next)
以查找next
指针,将其加载到寄存器中,然后返回到调用程序。 The contents of node
may be manipulated by another thread of execution in the meantime. 同时,
node
的内容可能会被另一个执行线程操纵。
... HOWEVER ... ...但是...
"Writers" (like add or remove node) MUST be mutually exclusive. “作家”(如添加或删除节点) 必须互斥。 Critical section is a good choice.
关键部分是一个不错的选择。
"Readers" (like "next") can run concurrently with each other. “读者”(例如“下一个”)可以彼此并发运行。
SUGGESTION: 建议:
If you can target Windows Vista or higher, consider using an SRW lock instead: 如果可以使用Windows Vista或更高版本,请考虑使用SRW锁:
While I think the answer by sarnold is correct, I just wanted to point out that the sizeof() call in your malloc() call in CreateList appears to have a bug. 虽然我认为sarnold的答案是正确的,但我只是想指出,CreateList中malloc()调用中的sizeof()调用似乎有一个错误。 I believe it should be:
我相信它应该是:
List *pList = malloc(sizeof(List));
The way you had it, you will create enough memory to hold a pointer to a List and not the List structure. 按照这种方式,您将创建足够的内存来保存指向 List而不是List结构的指针 。 (You may also want to cast the return type to (List*) and compare it to NULL before using it..)
(您可能还希望将返回类型强制转换为(List *)并将其与NULL比较,然后再使用。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.