[英]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.