用C语言如何实现多线程同时运行的情况下,各个线程输出不同的随机数?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用C语言如何实现多线程同时运行的情况下,各个线程输出不同的随机数?相关的知识,希望对你有一定的参考价值。
我用系统时间作为种子,发现因为各个线程之间运行的时间差太小,所以产生的随机数还是相同的。网上有种方法可以用微秒级的时间作种子,但我没看懂,不知道谁能帮忙解释下不?或者有其他方法也欢迎提出。不过在srand前让线程sleep的方法就不需要了,因为我这里的情况要求线程之间要同时运行。
1、使用pthread库执行多线程,这个是Linux下的线程库 Windows下应该有自己的API,不过这种东西一般还是以Linux为标准。pthread_create()创建一个线程,传入fun()的函数指针就行了。然后这个Beep()的需求要进行线程间通信,可以用共享内存的方法,设一个bool变量flag共享,然后beep的时候设为false,beep完设成true。fun()里面每次看一下这个flag,是false的话就不做动作等下一秒,基本可以满足需求。
2、例程:
#include <pthread.h>#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define MAX 10
pthread_t thread[2];
pthread_mutex_t mut;
int number=0, i;
void *thread1()
printf ("thread1 : I'm thread 1\\n");
for (i = 0; i < MAX; i++)
printf("thread1 : number = %d\\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(2);
printf("thread1 :主函数在等我完成任务吗?\\n");
pthread_exit(NULL);
void *thread2()
printf("thread2 : I'm thread 2\\n");
for (i = 0; i < MAX; i++)
printf("thread2 : number = %d\\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(3);
printf("thread2 :主函数在等我完成任务吗?\\n");
pthread_exit(NULL);
void thread_create(void)
int temp;
memset(&thread, 0, sizeof(thread)); //comment1
/*创建线程*/
if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0) //comment2
printf("线程1创建失败!\\n");
else
printf("线程1被创建\\n");
if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3
printf("线程2创建失败");
else
printf("线程2被创建\\n");
void thread_wait(void)
/*等待线程结束*/
if(thread[0] !=0) //comment4
pthread_join(thread[0],NULL);
printf("线程1已经结束\\n");
if(thread[1] !=0) //comment5
pthread_join(thread[1],NULL);
printf("线程2已经结束\\n");
int main()
/*用默认属性初始化互斥锁*/
pthread_mutex_init(&mut,NULL);
printf("我是主函数哦,我正在创建线程,呵呵\\n");
thread_create();
printf("我是主函数哦,我正在等待线程完成任务阿,呵呵\\n");
thread_wait();
return 0;
参考技术A 你用 (系统时间 - 线程 id*10) 作种子 就可以了。
种子变了,随机数系列就会变。
或 一个线程种子用 srand(1234); 另一个用 srand(4321); ...
加 系统时间 目的是 每次跑程序 随机数系列不同,更符合“随机”。本回答被提问者采纳
windows环境,多线程情况下,C语言向文件写入数据。
具体如下:
我试图向一个某文件中追加数据,最初写法是
FILE *fp = fopen(path,"a");
……
fclose(fp);
若单个运行做出的程序,追加1W个数据,可以实现
但如果有多个同样的程序运行,向同一个文件追加数据,会出现数据丢失的情况。
我记得可以在追加数据的时候锁定文件,避免数据丢失的情况,但是,貌似没弄成功
我希望求一个实例,要求如下:
1运行环境 Window
2要求能用GCC编译通过
3要求完整例子,包括:打开文件、锁定文件、输入数据、解除锁定、关闭文件
五个步骤
4如果可以,请尽量用FILE *fp = fopen(path,"a");打开
但实在不行,用CreatFile也可以 无论如何,请用 C/C++编写
5如果编写的代码符合工整,我会追加50分作为报酬
多谢前辈大神帮助
又PS:lilaosi2001先生的程序看起来很棒的样子,但我windows程序设计显然没学好,如果能把那几个涉及到API的宏解释下(比如“GENERIC_READ、GENERIC_WRITE”),那就更好了。。当然,即便您不愿下,我也一定会给您200分的
而lieyan2024先生,您觉得,不断地尝试打开文件再写入快呢,还是打开后不断尝试写入快呢?
twknq94 先生,请不要ctrl+C,ctrl+V.我没有用过goto,本专业的人都知道
②、你的目的性较强,但是你也想有更加明确的目标,我可以给你讲一下怎么自己去寻找目标和路线以及怎样学习。
③、计算机专业领域一共有几个大方向,十几个分支方向,而每个分支方向又有几十个小方向,每一个方向的深入学习与熟练到一定火候都不是一朝一夕,互相之间也不是完全没联系的,但是你现在就应该选择一个大方向并在其中的一个小方向内深入(为什么要这么早就选择具体的分支方向?后面说)。
④、这里列出计算机的几个大方向(非编程开发类的我就不说了):
基本方向:
1、单片机、嵌入式方向
2、网络编程:涉及到服务器程序、客户端开发、脚本设计等。
3、系统编程:基础API开发、桌面开发、系统程序开发、服务程序
4、图形学:3D、2D、图像识别、人脸识别
5、音频:语音识别、音频解码、音频软件
6、编译原理:编译器设计、脚本解释器、虚拟机、非自然语言翻译系统
7、应用层开发:利用高层语言去开发表层应用
8、安全:反工程、病毒、反病毒、木马、反木马、软件破解、软件加壳
附加方向:
8、人工智能:遗传算法、神经网络、灰色系统等等
9、游戏设计:各种游戏引擎设计以及业务逻辑设计等
⑤、基本方向是你一定要选的,附加方向只是基于基本方向的一些锦上添花,但是不管你怎么选,最开始某些东西一定要深入而不是只是懂就够(当然你对自己要求似乎不会很低),我把这个列出来:
数据结构:下面其他理论的基础。
操作系统原理:理解操作系统的架构和细节,你才能对以后关于多线程、文件管理、内存管理、指令优先级等有一个正确理解和运用。
编译原理:能够升华你对计算机编程语言的理解,对以后出现的各种编译、解释、兼容、移植、优化、并发与并行算法等有一个深入理解。
数据库系统原理:这个是进入公司都要会的,也是大型软件开发的基础。
软件工程:这个是你能够在经验不足还能保证大项目正常完成的理论基础。
网络技术:这个是必须学的,因为目前几乎没有一款装几率很高的软件或者平台跟网络无关。
数学的话,主要是:离散数学、线性代数、高等数学、计算机图形学、概率论
以上几个基础就是你成为一个融汇各个主要分支牛人必须学的(当然不是指理论,而是理论+实践编码能力)
⑥以上都是大的基础,要一一攻破并深入学习,虽然网络时代计算机专业知识爆炸式的增长,但是以上几个基础掌握后,会发现,以后的什么新的理论和技术都是基于这些大基础,你就很容易理解了。
⑦我为什么开头不讲你要具体学什么怎么顺序学呢?因为那些技术你要掌握的话,根本可以自己解决,但是如果你由于兴趣,沉迷于一些自己可见的小范围技术的话,那么毕业后虽然也能找到不错的工作,薪水也可能高,但是不能成为一个大牛。
现在才开始讲学习顺序,虽然你说不要推荐书,不过我还是要用书来做顺序。
C语言是可以写很多核心和高级的东西,而不只是小东西,但是从你代码来看,居然用到了 goto,我不是说你那些程序用到GOTO有什么不好,而是一定要避免用GOTO,goto是错误之源,如果你有什么内容非要用到goto才能写到,说明你的编码技巧还有不少提高空间。
你的学习顺序应该是:
C:做一个超级马里奥出来,并能够读取文本脚本来更新关卡。
C++:写一个2D图形引擎,封装掉细节,实现面向对象设计和可复用设计,并且用到《设计模式》中提到的一些设计模式,这样才能算对C++有一个很好的掌握。
MFC:MFC技术虽然近期已经冷下来了,但是你能熟练掌握它,才能证明你的C++OO技术够纯熟,严格证明你掌握了MFC很简单,你只要用MFC做出一个杀毒引擎就差不多了。推荐的书有《深入浅出MFC》。
《Windows程序设计》:和MFC不同的是,用的是windows核心SDK,也就是API,这本书学完后,你才能从操作系统层面上算掌握了win32 平台下的机理(其实win64和win32大部分机理类似)。
C#:C#里集合了当代和前沿计算机科学里最先进的一些语法(虽然执行效率一直被人质疑),但是你学完C#并深入后,至少能够算是对计算机语言有一个更加深刻的理解了。如何证明你C#学的不错了?也很简单,再次写一个随便什么游戏,比如俄罗斯方块。如果更加证明自己呢?用它写一个P2P网络对战游戏。
(如果你注意的话,会发现我说的学习顺序都是沿着语言和某些技术的,为什么呢?因为这些语言和技术涉及到特定的领域技术和计算机理论思想,比如学完了C#的话,就不单指学完了C#,而是把多种语言范式都学习了一遍,以及现代的程序开发思维(因为里面用到了很多让你一劳永逸的技术))
以上5个步骤都是基础大步骤,要解决的话要没1-2年应该不够。
与此同时,要尽快选出文中你感兴趣的方向作为3-5年的长期方向,不要担心过早选择分支方向会有什么损失,因为计算机很多分支是相通的,只有你把分支方向深入进去,才能真正理解很多理论的实践意义。并且一旦你在某个分支领域形成了较强的优势(比如,到公司里只有你这方面最强),那么你就是稀缺人才。
关于大方向的步骤就不说了,你主要就是要把我说的这几个基础步骤先解决,同时平时要注重大方向理论结合实际去编码和开发。 参考技术A 下面的程序,编译之后,你可以运行很多个实例,目前我将文件写在了D:\1.txt,每个程序写1000行数据,这些值你可以自己更改(比如 写在C:,每个程序写10000行等),等程序都写完后,你可以去文件中查看写文件的结果。补充一下,我是在VC6.0环境中写的,所以windows.h,如果你不是在这个环境中的话,可能需要修改一些定义,比如DWORD等。其他的API都是windows平台提供的API;
#include <stdio.h>
#include "windows.h"
int main()
//获取进程ID,因为你希望是多个进程运行同时写一个文件,所以,我们打印出进程ID
DWORD dwProcessID = GetCurrentProcessId();
//初始化我们要写入文件中的内容,及该内容长度;
char szContent[100] = 0;
sprintf(szContent,"process[%u] write file\r\n",dwProcessID);
DWORD dwContentLen = strlen(szContent);
//创建互斥量,这样可以进行进程间的互斥,当然用这个也可以做线程间的互斥
HANDLE hMutex = CreateMutex(NULL,FALSE,"MyFileMutex");
if (NULL == hMutex)
printf("[%u]Create/Open Mutex error!\r\n",dwProcessID);
return 1;
//创建或打开文件
HANDLE hFile = CreateFile("D:\\1.txt",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_ARCHIVE,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
printf("[%u]Creat/Open file error!\r\n",dwProcessID);
return 1;
//循环写入文件
for(int i = 0; i < 1000 ; i++)
//等待临界资源,即锁定文件
WaitForSingleObject(hMutex,INFINITE);
printf("Process[%u] Get the signal\r\n",dwProcessID);
DWORD len = 0;
//因为是共享写文件,即多个程序写一个文件,所以一定要将文件指针偏移到尾部
SetFilePointer(hFile,0,NULL,FILE_END);
//写入文件
BOOL rnt = WriteFile(hFile,szContent,dwContentLen,&len,NULL);
if (rnt == FALSE)
printf("Process[%u] Fail to write file\r\n",dwProcessID);
//释放互斥量,解除锁定
ReleaseMutex(hMutex);
//加个Sleep便于我们中间观察结果
Sleep(30);
CloseHandle(hMutex);
CloseHandle(hFile);
return 0;
应你要求,我把AIP中的宏定义解释如下:
HANDLE hFile = CreateFile("D:\\1.txt",
GENERIC_READ | GENERIC_WRITE,//表示程序对该文件有读和写的权限
FILE_SHARE_WRITE | FILE_SHARE_READ,//表示可以多个程序共享读和写的权限
NULL,
OPEN_ALWAYS,//表示打开该文件,如果该文件不存在,则创建该文件
FILE_ATTRIBUTE_ARCHIVE,//文件的属性为存档
NULL);
WaitForSingleObject(hMutex,INFINITE);
//INFINITE表示永远等待,直到hMutex有信号为止
SetFilePointer(hFile,0,NULL,FILE_END);
//FILE_END表示从文件尾部开始偏移;实际此举就是将文件指针偏移到文件尾部;本回答被提问者采纳 参考技术B 丢失的问题是程序设计的问题,你写文件实际上只能是向一个写,这个磁盘的物理结构决定的。如果你要多个数据来源的话,就设计一个异步的buffer,写文件时向这个buffer写入,另外一个单独的线程就检查这个buffer,发现有数据就向文件中追加。这样设计就不会丢失数据了。
接口类似:
class AsyncBuffer
virtual bool isEof() = 0;
virtual void write(const unsigned char* data, unsigned int size) = 0;
virtual unsigned int read(unsigned char* buff, unsigned int szBuf) = 0;
;
使用如下:
AsyncBuffer asyncBuff;
thread1:
asyncBuf.write(...);
thread2:
asyncBuf.write(...);
write file thread:
FILE* fp = fopen(...);
while(!end)
if(asyncBuf.isEof()) Sleep(10);
asyncBuf.read(....);
fwrite(...);
fclose(fp); 参考技术C .......
补充:
.......
又补充:
大约一个正常人都会认为这个公式是正确的:打开 + 写入 > 写入。
这说明楼主你是对的。
既然有了正确答案,那我们也就不再继续深究了。
以上是关于用C语言如何实现多线程同时运行的情况下,各个线程输出不同的随机数?的主要内容,如果未能解决你的问题,请参考以下文章