簡體   English   中英

C ++列表彈出和推送數據競賽

[英]C++ List pop and push data race

對於std :: list l,在線程1中,我做了l.push_back。在線程2中,我做了while(l.size()> 1)l.pop_front()當這兩個線程同時運行時,我得到了數據競爭。

令我感到困惑的是,我在pop_front之前檢查了l.size是否大於1,所以,當push_back時,在任何情況下都沒有將對象推回Null的前身,那么我就無法理解為什么會發生數據爭用在這。

下面是我測試中的代碼:

#include <windows.h>
#include <list>

using namespace std;

HANDLE gsem = CreateSemaphore(NULL, 2, 2, NULL);
unsigned long __stdcall threadPoc(list<int>* l);
unsigned long __stdcall threadPoc2(list<int>* l);
int main()
{
  std::list<int> l;
  unsigned long a1, a2;
  HANDLE t[2];
  t[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadPoc, &l, 0, &a1);
  t[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadPoc2, &l, 0, &a2);

  ReleaseSemaphore(gsem, 2, NULL);

  WaitForMultipleObjects(2, t, TRUE, INFINITE);

  return 0;
}
bool exf = false;
unsigned long __stdcall threadPoc(list<int>* l)
{
  WaitForSingleObject(gsem, INFINITE);
  for (int i=0; i<100000; i++)
    l->push_back(i);
  exf = true;
  return 0;
}

unsigned long __stdcall threadPoc2(list<int>* l)
{
  WaitForSingleObject(gsem, INFINITE);
  while (l->size()>1 || !exf)
    l->pop_front();
  return 0;
}

將元素添加到列表的后面時,通常需要執行以下操作:

  1. 取列表的最后一個元素
  2. 讓列表中的最后一個元素指向新元素
  3. 讓新元素向后指向最后一個元素
  4. 讓列表指向新的最后一個元素

如果您的列表包含1個元素,並且另一個線程在步驟1和2之間刪除了該元素,則您的列表將被破壞。

使用互斥鎖(CriticalSection)保護您的列表,或使用無鎖列表(例如,來自Microsoft PPL庫的current_queue,請參閱http://msdn.microsoft.com/zh-cn/library/dd504906.aspx#queue )。

並發性是一個大話題,首先,我請您閱讀Anthony Williams的“ C ++並發性”,在讀完本書之后,您幾乎可以理解所有內容。

首先,請記住一件事,當一個線程被寫入而另一線程被讀/寫到同一對象時,總是存在沖突。

其次,對於您的特定問題,顯然有幾個沖突的地方。

  1. l.push_back最有可能(取決於列表實現)更改大小,l.size()是讀取,因此在相同的變量大小上是寫-讀沖突。 而且l.pop_front很有可能也會更改大小,因此這是一個寫-寫沖突。 考慮當push_back和pop_front都更改大小時,該大小將損壞。

  2. 似乎l.push_back和l.pop_front沒有寫-寫沖突,因為C ++的列表是一個雙鏈表,而push_back / pop_front沒有處理相同的變量,但是您可能錯了。 一件顯而易見的事情是,push_back()可能涉及內存分配,pop_front()可能涉及內存釋放。 內存內容由模板ID Alloc處理。 您很有可能發生內存分配/取消分配沖突。 這完全取決於實現,其中不同的庫可能具有不同的實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM