我已经包含了一个可以编译的源代码,并为自己查看问题。用g ++ -lpthread list-memchk.cpp -o list-memchk
编译以此为例,./list-memchk 43000000 30000000 10
我已经包含了三个文件,第一个,
列表memchk.cpp
#include <cstdlib>
#include <iostream>
#include <pthread.h>
using namespace std;
struct node
{
public :
unsigned int part1; // 4 bytes
unsigned int part2; // 4 bytes
node *next; //pointer, 8 bytes on 64 bit system
unsigned int read_part1();
};
struct LinkedList
{
public:
LinkedList();
void insert(unsigned int data[], unsigned int data1);
bool isEmpty() const;
node* head;
};
unsigned int node::read_part1() {
return part1;
}
LinkedList::LinkedList():
head(NULL)
{
}
bool LinkedList::isEmpty() const
{
return (head == NULL);
}
void LinkedList::insert(unsigned int data[], unsigned int data1)
{
node* oldHead = head;
node* newHead = new node();
newHead->part1 = data[0];
newHead->part2 = data1;
newHead->next = oldHead;
head = newHead;
}
unsigned int allocations = 300000000;
unsigned int index_size = 430000000;//index of lists, 430m,.
pthread_mutex_t mutex;
//will be creatad on heap
LinkedList *list = NULL;
unsigned long node_count() {
unsigned long numNodes = 0;
for (int i=0; i<index_size; i++)
{
node* current = list[i].head;
// if root is null, the number of nodes is 0
if(current != NULL) {
// if root is not null, we have at least one node
numNodes++;
// count all nodes
while(current->next != NULL) {
numNodes++;
current = current->next;
}
}
}
return numNodes;
}
#include "alloc_threads.cpp"
void start_threads(int thread_count) {
alloc_threads alloc_thr[thread_count];//thread objects
pthread_t threads[thread_count];
pthread_mutex_init(&mutex, NULL);
for (int i=0; i<thread_count; i++)
{
alloc_threads *rr;
rr = new alloc_threads(list, mutex, allocations);
alloc_thr[i] = *rr;
pthread_create(&threads[i], NULL, &alloc_threads::allocation_helper,&alloc_thr[i]);
delete rr;
}
for (int i=0; i<thread_count; i++)
pthread_join( threads[i], NULL);
}
int main(int argc, char *argv[])
{
if ( argc < 4 )
{
std::cout << "Missing paramaters. " << endl;
std::cout << "Please run me like this : <list-memchk> <index_size> <allocations_per_thread> <thread_count>" << endl;
return 1;
}
index_size = strtoul(argv[1], 0, 10);
allocations = strtoul(argv[2], 0, 10);
unsigned int thr_cnt = strtoul(argv[3], 0, 10);
LinkedList list_instance;
cout << "1 LinkedList instance takes [" << sizeof(list_instance) << "] bytes in memory!"<< endl;
node node_instance;
cout << "1 node instance takes [" << sizeof(node_instance) <<"] bytes in memory !"<< endl;
list = new (nothrow) LinkedList[index_size];
if (!list)
{
cout << "Error allocating memory" << endl;
return 1;
}
unsigned int some_data[] = {00, 01};
unsigned int index;
cout << "Allocating ..." << endl;
start_threads(thr_cnt);
unsigned long sk = ((allocations * sizeof(node_instance) + index_size*sizeof(list_instance))) / (1024*1024*1024);
cout << "This process *should* consume around " << sk <<" GBytes of memory, but does it ?"<< endl;
cout << "Allocating done, *check the process size* ..." << endl;
cout << "Lets count `nodes` to see how many do we have; counting, please wait ..." << endl;
cout << "We have reached [" << node_count() << "] nodes, expected [" << allocations * thr_cnt << "] nodes. You may press any number key to exit." << endl;
string s;
getline(std::cin, s);
return 0;
}
然后, alloc_threads.cpp
#include "alloc_threads.h"
using namespace std;
alloc_threads::alloc_threads()
{
}
void *alloc_threads::allocation_helper(void *context)
{
return ((alloc_threads *)context)->allocation();
}
alloc_threads::alloc_threads(LinkedList* x_list, pthread_mutex_t x_mutex, unsigned int x_allocations)
{
list = x_list;
mutex = x_mutex;
allocations = x_allocations;
}
void * alloc_threads::allocation(void)
{
cout << "Thread started" << endl;
unsigned int some_data[] = {00, 01};
unsigned int index;
unsigned short inde;
LinkedList *list_instance2 = NULL;
for (int i=0; i<allocations; i++)
{
pthread_mutex_lock(&mutex);
index = rand();
inde = (unsigned short)index;
list_instance2 = &list[inde];
list_instance2->insert(some_data, some_data[1]);
pthread_mutex_unlock(&mutex);
}
cout << "Thread finished" << endl;
return 0;
}
alloc_threads::~alloc_threads()
{
}
最后, alloc_threads.h
class alloc_threads{
public:
void *allocation(void);
static void *allocation_helper(void *context);
alloc_threads();
alloc_threads(LinkedList *x_list, pthread_mutex_t x_mutex, unsigned int x_allocations);
~alloc_threads();
private:
pthread_mutex_t mutex;
LinkedList* list;
unsigned int allocations;
};
代码本身根本没有评论,但希望它并不难理解。我所做的,就是在多个并发线程中使用标准分配器分配内存,例如,10。在所有线程中完成分配后,我访问每个节点并在成功访问时递增numNodes
。我通常得到的是,numNodes
值比预期的更少/几百或几千。怎么了 ?并且,我已经用两个不同的分配器完成了这两个,它们都有相同的行为。
答案 0 :(得分:0)
看来,我以错误的方式使用互斥锁 - 它不会阻止并发线程写入相同的内存。
我发现的solution
是:在list-memchk.cpp中定义互斥变量并避免将其传递给线程但使用它as is
。
list-memchk.cpp: 用这个替换互斥锁定义,
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ;
删除
pthread_mutex_init(&mutex, NULL);
alloc_threads.h: 从此文件中删除互斥锁;
alloc_threads.cpp:
删除mutex = x_mutex;
多数民众赞成。不再缺少节点。但是,分配速度很慢。看起来线程正在等待解锁互斥锁; cpu核心是空闲的,分配需要花费大量时间。