求大神指点!线程安全型双向链表的实现 代码出现问题

问题描述

#include<stdio.h>//c语言标准输入输出头文件#include<malloc.h>//动态存储分配函数头文件#include<stdlib.h>//标准库头文件(malloc(),rand(),srand()等等)#include<process.h>//包含用于和宏指令的作用声明与螺纹和过程一起使用的C标头文件(线程的创建和终结等等)#include<windows.h>//win32头文件#include<time.h>//日期和时间头文件#definerandom(x)(rand()%x)//产生随机数#definecr1//1标识为插入#definesc0//0标识为删除volatileintreadcount=0;//读者数目constintlsarea=10000;//链表大小随机数constintearea=10000;//元素范围随机数constintsum=100000;//线程运行总次数intth=0;//初始化当前线程总数intth_cz=1;//初始化当前查找线程总数intth_cr=1;//初始化当前插入线程总数intth_sc=1;//初始化当前删除线程总数HANDLEh_Mutex;//控制读者数量readcount的互斥访问量HANDLEmutex;//控制读写互斥,写写互斥的信号量typedefintElemType;//定义ElemType为int类型的别名typedefstructDuLNode*PNode;//结点指针//定义结点结构体typedefstructDuLNode{ElemTypedata;//定义数据域PNodeprior;//定义前驱指针PNodenext;//定义后继指针}DuLNode,*DLN;//定义双向链表结构体typedefstructDuLinkList{DLNhead;//定义头结点intLength;//定义链表长度}DuLinkList,*DLL;//定义读者传参结构体structReadarg{DLLList;//定义链表ElemTypee;//定义查找元素};//定义写者传参结构体structWritearg{DLLList;//定义链表intadd;//定义插入或删除的位置ElemTypee;//定义插入元素intFlag;//定义传入标示符(cr执行插入操作,sc执行删除操作)};//初始化一个空的双向链表并创建链表voidInitList(DLLL){intc,i,e;//定义三个整型变量c,i,eDLNp;//定义结点p//初始化操作L->head=0;//链表头结点置零L->Length=0;//链表长度置零//创建操作printf("双向链表初始化完毕n");srand((int)time(0));//随机数时间种子设置c=random(lsarea);//变量c取范围0~Lsarea内的随机整数if(!c){printf("链表创建失败!n");exit(0);//异常处理,如果用户未输入结点个数则跳出该段代码。}else{p=(DuLNode*)malloc(sizeof(DuLNode));//p动态分配存储空间if(!p){printf("结点p动态分配内存失败!n");exit(0);//异常处理,如果节点p动态分配内存失败则跳出该段代码。}e=random(earea);//变量e取范围0~earea内的随机整数p->data=e;//将变量e的值送入结点p的数据域p->next=p->prior=p;//将结点p的前驱和后继指针指向它自己L->head=p;//将p结点作为链表头结点L->Length++;//链表长度加1//下面循环插入后续结点操作for(i=1;i<c;i++){p=(DuLNode*)malloc(sizeof(DuLNode));//p动态分配存储空间if(!p){printf("结点p动态分配内存失败!n");exit(0);//异常处理,如果用户未输入结点个数则跳出该段代码。}e=random(earea);//变量e取范围0~earea内的随机整数p->data=e;//将变量e的值送入结点p的数据域p->next=L->head;//将结点p的后继指针指向当前链表的头结点p->prior=L->head->prior;//结点p的前驱指针指向当前链表的尾结点L->head->prior->next=p;//将当前链表尾结点的后继指针指向结点pL->head->prior=p;//将当前链表头节点的前驱指针指向结点pL->Length++;//链表长度加1}}}//在链表指定位置插入一个结点voidInsert(DLLL,inti,ElemTypee){DLNp,q;//定义结点p,qintj;//定义整型变量j//下面判断插入位置是否合法if(i<1||i>L->Length+1){printf("对不起,您插入的位置超过了链表范围!nn");}else{printf("恭喜你,插入成功!nn");p=(DuLNode*)malloc(sizeof(DuLNode));//p动态分配存储空间if(!p){printf("结点p动态分配内存失败!n");exit(0);//异常处理,如果用户未输入结点个数则跳出该段代码。}q=L->head;//q指向当前链表头结点p->data=e;//将变量e的值送入结点p的数据域if(!L&&i==1){//判断链表为空并且插入第一个元素的情况p->next=p->prior=p;//将结点p的前驱和后继指针指向它自己L->head=p;//将p结点作为链表头结点L->Length++;//链表长度加1}else{if(i==1||i==(L->Length+1)){//判断链表不为空在当前表头或表尾插入结点q=q->prior;//将q指向当前链表尾结点p->next=q->next;//将p的后继指针指向当前链表头结点p->prior=q;//将p的前驱指针指向当前链表的尾结点q->next->prior=p;//将当前链表头结点的前驱指针指向结点pq->next=p;//将当前链表尾结点的后继指针指向结点pL->Length++;//链表长度加1if(i==1)//判断插入位置是否是头结点L->head=p;//将结点p置为链表头结点}else{for(j=1;j<i;j++){//循环定位插入位置q=q->next;}q->prior->next=p;//将当前链表尾结点的后继指针指向结点pp->prior=q->prior;//将结点p的前驱指针指向当前链表的尾结点q->prior=p;//将当前链表头结点的前驱指针指向结点pp->next=q;//将结点p的后继指针指向当前链表头结点L->Length++;//链表长度加1}}}}//删除指定位置的结点voidErase(DLLL,inti){DLNq;//定义结点qintj;//定义整型变量jq=L->head;//q指向当前链表头结点if(i<1||i>(L->Length)||L->head==NULL){printf("对不起,您删除的位置超过了链表范围或者链表为空!nn");}else{printf("恭喜你,删除成功!nn");for(j=1;j<i;j++){//循环定位删除位置q=q->next;}q->prior->next=q->next;//将结点q前一个结点的后继指针指向q的后一个结点q->next->prior=q->prior;//将结点q后一个结点的前驱指针指向q的前一个结点if(i==1){//判断删除的位置是否是链表头结点L->head=q->next;//将当前链表的头结点指向第二个结点}L->Length--;//链表长度减1if(L->Length==0){//判断当前链表是否为空L->head=NULL;//将当前链表头结点置空}free(q);//释放结点q的物理内存}}//删除链表中所有结点voidClear(DLLL){DLNq,temp;//定义结点q,tempinti,j;//定义整型变量i,ji=L->Length;//将链表长度赋给itemp=q=L->head;//结点q和temp指向当前链表头结点for(j=0;j<i;j++){//循环释放每一个结点q=q->next;free(temp);temp=q;L->Length--;}L->head=NULL;//链表头结点置空printf("链表已清空!");}//查找链表中是否有指定的元素,若有,返回能够访问该结点的指针;若无,返回NULLDLNFind(DLLL,ElemTypee);//打印当前链表中的所有元素voidPrint(DLLL){DLNp;//定义结点pif(L->head==NULL){printf("链表为空!");}else{p=L->head;printf("%d",p->data);p=p->next;//当p重新指到链表头节点的时候跳出循环while(p!=L->head){printf("%4d",p->data);p=p->next;}}printf("n");printf("长度为:%dn",L->Length);printf("打印完毕!nn");//读者线程(查找)unsigned__stdcallReaderThread(void*arg){Readarg*RA;RA=(Readarg*)arg;inte;WaitForSingleObject(h_Mutex,-1);//等待互斥量信号readcount++;if(readcount==1){WaitForSingleObject(mutex,INFINITE);//等待信号量信号}ReleaseMutex(h_Mutex);//释放互斥量信号e=RA->e;printf("查找操作:读者%d开始查找%dn",th_cz,e);Find(RA->List,e);th_cz++;//执行完一遍查找读者数加1WaitForSingleObject(h_Mutex,-1);readcount--;if(readcount==0){ReleaseSemaphore(mutex,1,NULL);//释放信号量信号}ReleaseMutex(h_Mutex);return0;}//写者线程(包括插入和删除)unsigned__stdcallWriterThread(void*arg){Writearg*WA;WA=(Writearg*)arg;intf,add,e;f=WA->Flag;add=WA->add;e=WA->e;if(f){WaitForSingleObject(mutex,INFINITE);printf("插入操作:写者%d开始在第%d位置插入元素%dn",th_cr,add,e);Insert(WA->List,add,e);th_cr++;//执行完一遍插入写者数加1Print(WA->List);ReleaseSemaphore(mutex,1,NULL);}else{WaitForSingleObject(mutex,INFINITE);printf("删除操作:写者%d开始删除第%d个位置n",th_sc,add);Erase(WA->List,add);th_sc++;//执行完一遍删除写者数加1Print(WA->List);ReleaseSemaphore(mutex,1,NULL);}return0;}intmain(){charsr;printf("**************************n");printf("1.读者优先n");printf("2.退出窗口n");printf("**************************n");printf("请输入你的选择(1或者2):");do{sr=(char)getchar();}while(sr!='1'&&sr!='2');//system("cls");if(sr=='2')return0;else{HANDLEhThread[sum];unsignedthreadID[sum];inti,j,k,m;DLLL;L=(DuLinkList*)malloc(sizeof(DuLinkList));InitList(L);Print(L);h_Mutex=CreateMutex(NULL,FALSE,NULL);//创建互斥量h_Mutexmutex=CreateSemaphore(NULL,1,1,NULL);//创建信号量mutexsrand((int)time(0));for(i=0;i<sum;i++){j=random(3);//在0,1,2这三个数内随机取一个值决定该次循环执行哪一个操作(0为查找,1为插入,2为删除)if(j==0){Readarg*RA=newReadarg[1];RA[0].List=L;RA[0].e=random(earea);//创建读者线程hThread[i]=(HANDLE)_beginthreadex(NULL,0,ReaderThread,(void*)&RA[0],0,&threadID[i]);}else{Writearg*WA=newWritearg[2];WA[0].List=L;WA[0].add=random(lsarea);WA[0].e=random(earea);WA[0].Flag=cr;WA[1].List=L;WA[1].add=random(lsarea);WA[1].e=0;WA[1].Flag=sc;//k=i;//m=k%4;if(j==1){//创建写者线程(插入)hThread[i]=(HANDLE)_beginthreadex(NULL,0,WriterThread,(void*)&WA[0],0,&threadID[i]);}else//创建写者线程(删除)hThread[i]=(HANDLE)_beginthreadex(NULL,0,WriterThread,(void*)&WA[1],0,&threadID[i]);}WaitForSingleObject(hThread[i],INFINITE);//循环内wait操作,及时收回线程}for(i=0;i<sum;i++){CloseHandle(hThread[i]);}CloseHandle(h_Mutex);CloseHandle(mutex);th=(th_cz+th_cr+th_sc)-3;//统计总线程数printf("当前查找读者人数为:%d;当前插入写者人数为:%d;当前删除写者人数为:%d;当前总人数为:%dn",th_cz-1,th_cr-1,th_sc-1,th);Clear(L);Print(L);printf("所有线程都执行完毕了。n");}return0;}cuo'qu

解决方案

解决方案二:
错误
解决方案三:
有人吗?求指点!!!

时间: 2024-06-16 11:30:04

求大神指点!线程安全型双向链表的实现 代码出现问题的相关文章

java-Java中同步线程不是应该先中断先继续吗,为什么我的没有?求大神指点

问题描述 Java中同步线程不是应该先中断先继续吗,为什么我的没有?求大神指点 代码如下: public class BuyTicketMain { public static void main(String args[ ]) { TicketHouse officer = new TicketHouse(); Thread zhangfei,likui,wangwu; zhangfei = new Thread(officer); zhangfei.setName("张飞"); l

线程-求大神指点,小弟拜上,弱鸡一个,请不吝赐教

问题描述 求大神指点,小弟拜上,弱鸡一个,请不吝赐教 MFC中可不可以使用WaitForSingleObject使一个OnTimer线程挂起呢,为什么我写的程序直接就跳过了WaitForSingleObject了呢 解决方案 OnTimer?定时器不是线程 解决方案二: 定时器消息在主线程中,不是可等待信号,wait不起作用的 解决方案三: 你WaitForSingleObject调用失败了吧~你Wait什么内核对象?

大数据-orcale大量数据分组查询报错求大神指点

问题描述 orcale大量数据分组查询报错求大神指点 对一个表数据进行分组查询,但是数据量太大了,当时是3000w条,跑着就报错了,数据库内部错误,也不是很懂.想请教下group by的时候是否数据量太多会报错,如果是它可以承受多大的数据量分组查询. 解决方案 肯定会报错,数据量大就会请求超时 解决方案二: 建议使用索引,给需要分组的字段加索引 解决方案三: 你可以试试根据你当前数据库的配置情况,进行分组查询的时候,使用多线程的方式进行查询 例如: select /*+ parallel(t,1

java中网络编程关于使用ObjetInputStream传输报错的问题,求大神指点

问题描述 java中网络编程关于使用ObjetInputStream传输报错的问题,求大神指点 以下贴出来的代码为通过ObjectInputStream(OutputStream)在客户端与服务器端之间交互时传输的对象,提供的图片中一个是客户端的代码片段,一个是服务器端的代码片段. 现在问题出在当客户端输完账号密码点击确定时,客户端卡死(应该是线程阻塞).服务器端抛出异常 :java.lang.ClassNotFoundException: com.wish.data.TransferObjec

加锁-求大神指点 ,Winform 问题

问题描述 求大神指点 ,Winform 问题 求大神指点,小弟感激不尽 我在Winform中 使用了多线程 还有的 加锁 把自己给高蒙了 求指点!!! 解决方案 所以基础很重要,该学的不学,要写程序了才想到学一点,那么当然举足无措了. 解决方案二: 如果你一瞧不通,并且你只对完成程序这个结果感兴趣,这样的情况下,花钱雇人或者外包项目是最佳的选择. 解决方案三: 通常多线程对同一资源操作的话,会有同步问题.如果希望同一时刻对某资源只有一个线程可以访问,就需要同步的方法.同步有很多种方法,你说的加锁

在Fragment中添加了一个按钮跳转到activity,但是一按按钮就闪退,求大神指点!!!

问题描述 在Fragment中添加了一个按钮跳转到activity,但是一按按钮就闪退,求大神指点!!! 这是错误日志: 我已经在网络请求的部分新建了一个子线程了,那为什么还是点击按钮就闪退呢,下面是新建的子线程,求大神指点迷津!!! public abstract class MyTimerCheck { private int mCount = 0; private int mTimeOutCount = 1; private int mSleepTime = 1000; // 1s pri

Spring MVC 多数据源,配置完事务之后就不能正常切换数据源,求大神指点

问题描述 Spring MVC 多数据源,配置完事务之后就不能正常切换数据源,求大神指点 两张附图事务没配置的时候数据源切换正常,加上事务之后就一直显示的是默认连接的数据源, 这是为什么啊??百思不得其解,,求神哥神姐解惑啊 这个是数据源切换代码 切换的时候就是 每次在掉底层方法之前先设置下数据库 向下面这样 MultipleDataSource.setDataSourceKey("yz_dataSource"); MultipleDataSource.setDataSourceKey

17岁...学Java,刚学完框架。,以后的路怎么走,求大神指点

问题描述 刚在培训机构学完Java课程,,就要就业了,,但是觉得很迷茫.不知道以后的路怎么走.学历...高中...瞬间就变成学历==压力了..想搞安卓,但是这刚毕业,继续java的路?学安卓可行吗?会影响以后的路吗?唉16岁的时候看同学搞了一个个人网站挺炫...想搞一个,一问价格,.,卧槽,,几千..学生哪买的起..想着自己做,买书啊,,看视频啊,,求指点啊..各种途径,最后搞出来了,,后面一段时间,帮别人开发,企业网站,(因为在县级城市,要求不那么高,有个域名,百度能收到,,网站漂亮ok完工.

android studio-这个问题有解决方法吗,求大神指点

问题描述 这个问题有解决方法吗,求大神指点 解决方案 这个方法已经废弃了,新sdk不再支持了,建议使用Notification notification = new NotificationCompat.Builder(context)...这种方式 解决方案二: 线程池问题,求大神解释 解决方案三: 是传完参数后出现的错误还是直接调用不了这个方法 解决方案四: 除非你把你的sdk调低点也可以

Genymoation安装之后打开虚拟机报错求大神指点

问题描述 Genymoation安装之后打开虚拟机报错求大神指点 错误是这样的 求大神指点,谢谢 解决方案 多启动几次,如果还不行,就启动virtualbox,在里面看看对应的虚拟机是否正常可以启动,或者先关掉它