当前位置:首页 > 编写线程安全的-队列-
什么是线程安全
要理解线程安全的概念,必须先理解以下知识点:
? 什么是临界资源:临界资源在多个进程或线程同时访问(读取和修改)时,
可能会产生错误的运行结果,其最终的运行结果依赖于多个进程或线程的指令执行顺序。例如,全局变量、全局数组、全局缓冲区、全局链表、全局队列都是典型的临界资源。
? 多进程或多线程访问临界资源的为什么会出现结果错误:进程或线程中的指
令执行是在操作系统的控制下,使用时间片轮转的方法,交替执行,各进程或线程的指令执行顺序是不可预知的,从而导致操作临界资源的最终结果不确定,这是一种错误。
? 什么是线程安全:线程安全就是通过对临界资源的访问加上互斥机制(通过
使用信号量),从而保证多个线程访问临界资源不会出现错误。线程安全隐含的意思是“无论各个线程如何交替使用CPU执行指令,对于各种情况,各线程对临界资源的访问结果永远都是正确的”。
? 什么是非线程安全: 非线程安全就是至少存在一种线程执行序列,使得线程
访问临界资源的结果出现错误,产生错误的原因是未对临界资源的访问实施保护,或者实施的保护措施不正确。
? 什么是线程安全的链表、队列、栈:就是多线程同时操作(包括查找、添加、
删除等)链表、队列或栈,无论如何操作,都不会产生错误的结果。此处,链表、队列或栈就是一种临界资源。
? 如何实现线程安全的链表、队列、栈:使用信号量机制实现各种数据操作间
的互斥。
具体举例如下:
1. 多次运行下面的代码,观察输出是否正确,思考产生错误的原因。 #include
volatile unsigned int gCount=0;
unsigned __stdcall FirstThreadFunc(void *pArguments) {
int i;
for(i=0; i<100000000; i++){
}
}
gCount=gCount+1;
return 0;
unsigned __stdcall SecondThreadFunc(void *pArguments) { } int main() {
hThread[0] = (HANDLE)_beginthreadex(NULL, 0, FirstThreadFunc, NULL, 0, &threadID[0]);
hThread[1] = (HANDLE)_beginthreadex(NULL, 0, SecondThreadFunc, NULL, 0, &threadID[1]); }
printf(\return 0;
// Destroy the objects. CloseHandle(hThread[0]);
WaitForSingleObject(hThread[1],INFINITE); WaitForSingleObject(hThread[1],INFINITE); HANDLE hThread[2]; unsigned threadID[2]; int i;
for(i=0; i<100000000; i++){ }
gCount=gCount+1;
return 0;
CloseHandle(hThread[1]);
该程序在main函数中创建了两个线程,每个线程分别对全局变量gCount进行100000000次的加1操作,在两个线程运行结束后,在主函数中输出最终的运行结果【即printf(\】。
按理说该结果应该是200000000,但多次运行后发现,并不是每次运行的结果都正确,部分如下图所示。
2. 下面的代码创建一个链表,创建两个子线程,每个子线程分别向该链表的末尾插入500000个节点【通过AddTail函数】。在两个线程运行结束后,使用stat函数统计当前链表中一共有多少个节点。按理说应该是有1000000个节点,多次运行该程序,观察输入结果是否正确,并思考产生错误的原因。
#include
#include
using namespace std;
const int NODENUM=500000;
struct node{ };
struct node *pHead=NULL, *pTail=NULL;
void AddTail(node* pNode){ }
void print() { }
void stat() {
int count=0; struct node *pCur; struct node *pCur; pCur=pHead;
while(pCur != NULL) { }
printf(\);
printf(\, pCur->id); pCur=pCur->pNext; if(pHead == NULL){ } else{ }
//当前链表不空 pTail->pNext=pNode; pTail=pNode; pTail->pNext=NULL; //当前链表为空链表 pHead=pNode; pTail=pNode; pNode->pNext=NULL; int id; char name[20]; struct node* pNext;
共分享92篇相关文档