多线程下读写vector变量

考虑到一个线程用于去读数据库,一次性插入多条数据到共享数据区,另外搞2个上的线程去读这个共享数据区,以后打算搞个线程池来处理读部分。

目下的问题是我想把这个共享数据区做成可变化的动态区,当读入数据大时,一次读入全部读完。当数据量小时,则在规范范围的空间中运行。

采用vector<mystructData>方式动态变化,比如要删除超过长度之外的设置,只需要earse就可以了,在线程中每次通过begin,end自动扫描处理中数据部分。

如果把线程部分放到dll中,那么考虑到如何读取共享数据区,采用导出函数方式,把主线程中的一个函数地址传入到dll中,然后在这个函数中通过

find_if(a.begin(),a.end(),myfunc)照样可以处理dll中跑线程的问题,之所以考虑用dll分离各个线程部分,是考虑到业务不同时,每个dll处理扫描共享数据区,发现自己的业务就去处理,不是则不理会,这样考虑设计可以通过编写dll方式来扩展不同的业务。

#include "stdafx.h"
#include <vector>
#include <iostream>
#include <windows.h>
#include <process.h>
#include <algorithm>

using namespace std;

struct te
{
	int IsGet;
	int a1;
	int s1;
	char b1[20];
};

bool isget(te t)
{
	return t.IsGet ==1;
}
bool getdata(te t)
{
	return t.IsGet==0;
}
vector<te> a; 
HANDLE hMutex;

void myprint(te t)
{ 
	cout<<"   ALL "<< (t.IsGet == 0? "Have": "No ")<< "("<<t.a1<<")"<<t.s1<<" " << t.b1 <<endl;

}

DWORD WINAPI insertdata( LPVOID lpParam )
{ 
	vector<te>::iterator p; 
	int i = 0;
	while (1)
	{  

		do{

			p = find_if(a.begin(), a.end(), isget);  
			if (p!= a.end())
			{      
				WaitForSingleObject(hMutex, INFINITE);
				i++;
				p->IsGet = 0; 
				p->s1 = i;
				sprintf(p->b1, "%s- %d", "thread_insert" , i); 
				cout<<" insert("<<p->a1<<") " << p->s1<<"  " << p->b1 <<endl;  
				ReleaseMutex(hMutex);
			}
			//Sleep(1000);

		}
		while(p != a.end());

		WaitForSingleObject(hMutex, INFINITE);
		cout<<"---------------------------"<<endl;
		for_each(a.begin(), a.end(), myprint);
		ReleaseMutex(hMutex);  
		Sleep(11000);
	}


	return 0;
}

//读线程,读完对IsGet标志为1
DWORD WINAPI processdata( LPVOID lpParam )
{
	vector<te>::iterator p;

	while(1)
	{
		WaitForSingleObject(hMutex, INFINITE);
		p = find_if(a.begin(), a.end(), getdata);
		if (p != a.end())
		{   
			cout<<"("<< (char*)lpParam << ") get (" << p->a1<<") " << p->s1 <<" " << p->b1 <<endl;   
			p->IsGet = 1;   
			p->s1 = 0;
			p->b1[0] = '\0';

		}  
		ReleaseMutex(hMutex);
		Sleep(500);
	}

	return 0;
}

int main(int argc, char* argv[])
{

	HANDLE hInsertHandle, hProcessHandle1,hProcessHandle2;
	DWORD dwThreadId;

	te tt1;
	for(int i = 0; i < 10;i++)
	{
		tt1.IsGet = 1;             //可以写入标志
		tt1.a1 = i;
		tt1.s1 = 0;
		sprintf(tt1.b1,"%d", i);
		a.push_back(tt1);
	}

	hMutex = CreateMutex(NULL, false, "mutex");

	hInsertHandle = CreateThread(
		NULL,                 
		0,                    
		insertdata,        
		NULL,                   // argument to thread function
		0,                           // use default creation flags
		&dwThreadId);

	hProcessHandle1 = CreateThread(  //读出线程1
		NULL,                 
		0,                    
		processdata,        
		"proc1" ,              
		0,                     
		&dwThreadId);
	hProcessHandle2 = CreateThread(
		NULL,                 
		0,                    
		processdata,        
		"proc2",            
		0,                  
		&dwThreadId);


	while(1)
	{ 
		printf("main thread ...\n");
		char c = getchar();
		if (c== 'q')
			break;
	}

	return 0;
}


### 返回 `std::vector` 的方法 在多线程环境中返回一个 `std::vector` 需要特别注意线程安全性和数据的一致性。以下是几种常见的实现方式及其注意事项。 #### 方法一:通过拷贝返回 可以通过函数直接返回一个 `std::vector` 对象,这种方式会触发拷贝操作或将对象移动到调用者栈上。由于 C++11 引入了右值引用和移动语义,这种做法通常性能开销较低。 ```cpp #include <iostream> #include <thread> #include <vector> std::vector<int> generateVector() { std::vector<int> vec; for (int i = 0; i < 10; ++i) { vec.push_back(i); } return vec; // 使用移动语义优化性能 } void processVector(const std::vector<int>& vec) { for (const auto& val : vec) { std::cout << val << " "; } std::cout << std::endl; } int main() { std::thread t([]{ std::vector<int> result = generateVector(); processVector(result); // 在子线程中处理 vector }); t.join(); return 0; } ``` 这种方法简单易用,但由于涉及拷贝或移动操作,在高并发场景下可能会带来额外的性能损耗[^1]。 --- #### 方法二:使用共享指针管理生命周期 为了减少不必要的拷贝并确保资源的安全释放,可以利用智能指针(如 `std::shared_ptr` 或 `std::unique_ptr`)来管理 `std::vector` 的所有权。 ```cpp #include <iostream> #include <memory> #include <thread> #include <vector> std::shared_ptr<std::vector<int>> createSharedVector() { auto vec = std::make_shared<std::vector<int>>(); for (int i = 0; i < 10; ++i) { vec->push_back(i); } return vec; } void useSharedVector(const std::shared_ptr<std::vector<int>>& vec) { for (const auto& val : *vec) { std::cout << val << " "; } std::cout << std::endl; } int main() { std::shared_ptr<std::vector<int>> sharedVec; std::thread t([&]() { sharedVec = createSharedVector(); // 子线程创建 vector 并存储到外部变量 }); t.join(); if (sharedVec) { useSharedVector(sharedVec); // 主线程使用共享的 vector } return 0; } ``` 此方法能够有效避免深拷贝带来的性能损失,并且通过智能指针自动管理内存,降低手动释放的风险[^2]。 --- #### 方法三:借助互斥锁保护共享访问 如果多个线程需要频繁读写同一个 `std::vector`,则应引入同步机制(如 `std::mutex`),以防止因竞争条件引发未定义行为。 ```cpp #include <iostream> #include <thread> #include <vector> #include <mutex> class SafeVector { public: void pushBack(int value) { std::lock_guard<std::mutex> lock(mutex_); data_.push_back(value); } const std::vector<int>& getData() const { return data_; } private: mutable std::mutex mutex_; // 可变修饰符允许常量成员函数加锁 std::vector<int> data_; }; void fillVector(SafeVector& sv, int start, int end) { for (int i = start; i < end; ++i) { sv.pushBack(i); } } void printVector(const SafeVector& sv) { for (const auto& val : sv.getData()) { std::cout << val << " "; } std::cout << std::endl; } int main() { SafeVector safeVec; std::thread t1(fillVector, std::ref(safeVec), 0, 5); std::thread t2(fillVector, std::ref(safeVec), 5, 10); t1.join(); t2.join(); printVector(safeVec); return 0; } ``` 上述代码展示了如何封装一个线程安全的容器类 `SafeVector`,并通过显式的锁定策略保障其内部状态一致[^3]。 --- #### 总结 以上三种方案各有优劣: - **方法一**适合轻量级任务,无需复杂控制逻辑; - **方法二**适用于需跨线程传递大容量数据的情形; - **方法三**针对高频次更新与查询需求设计,强调安全性而非效率。 实际开发时可根据具体应用场景灵活选用合适的技术手段。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值