关于多线程操作同一个队列时如何互斥
有一个接收线程,一个队列,N个处理线程;
a.接收线程负责不断接收数据包写入队列;
b.处理线程从队列中读取数据包后,删除该数据包,再处理数据包;
关于队列的读写操作,我担心N个处理线程同时读取了队列的同一个数据包,做删除时,删除了未读取的数据包;
想加个一个保护,线程依次访问,是否应该用互斥,该如何写?
[解决办法]
用临界区API
void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
就这么几个函数
每个线程要操作队列的时候,enter操作完毕后leave
[解决办法]
一般多线程中保持同步用的几种方式:
互斥,信号灯,临界,事件
[解决办法]
用 TThreadList 来管理
TMyStruct * AStruct = NULL;
try
{
TList * AList = FThreadList->LockList();
if (AList->Count)
{
AStruct = (TMyStruct *)AList->Items[0];
AList->Delete(0);
}
}
__finally
{
FThreadList->UnlockList();
}
if (AStruct)
{
// 处理这个 AStruct
delete AStruct;
}
[解决办法]
BCB有一个 TThreadList对象,它是线程安全的,不需要再使用其它同步方法了。
[解决办法]
class MyThread : public TThread
{
...
private:
TCriticalSection pLockX;
int x;
float y;
...
};
void __fastcall MyThread::Execute()
{
...
pLockX-> Acquire();//Here pLockX is a Global CriticalSection variable.
x++;
y=sin(x);
pLockX-> Release();
...
}
[解决办法]
queue<char*> g_TcpDataQueue1,如果里面存放的是字符串的话,很有可能有问题,建议如string或String来代替char*
只要做到对g_TcpDataQueue1的存取全部位于g_Lock->Acquire()和g_Lock->Release();之间,那就不会有问题,就是效率可能会有点慢。
[解决办法]
尽量少在acquire和release之间操作,让资源尽快释放给别的线程用
[解决办法]
如果当初放入队列的时候是用new 或malloc 申请的内存,放入队列应该不会有问题,如果是把一个AnsiString使用c_str()方法转换成char *放入队列,那就可能有问题。
楼主的接收的数据包里都是字符信息码? 如果有二进制数据用string处理不是好方法。
通常情况下数据包需要自己定义协议,如命令类型、数据类型、数据长度之类的信息,纯字符的通信情况较少吧。
效率问题应该是根据通讯速率,每个数据包处理的时间,线程的多少去优化,不是线程越多越好。CPU的核就那几个,线程多了调度放入开销就大。如果每个包处理的时间很短,多线程还不如单线程效率高。