关于多线程考贝的一些疑问
我测试了一个多线程考文件的一个程序,代码如下,发现在考贝中有一些数据考贝有误,希望大家能指证,说下怎么实现更好。
#include <iostream> #include <cstring> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <pthread.h> using namespace std; /************************************ *使用指定线程实现从文件的拷贝 *创建时间:2011.07.28 *修改时间:2011.07.29 *作者:hahaya ***********************************/ //最大使用的线程数 const int MAX_THREADS = 5; pthread_mutex_t readmutex;pthread_mutex_t writemutex; typedef struct TAG_INFO { char *fromfile; //源地址 char *tofile; //目的地址 int begin; int end;}info; //st_size的类型为__off_t int get_size(const char *filename) { struct stat st; memset(&st, 0, sizeof(st)); stat(filename, &st); return st.st_size; } void* threadDL(void *param) { info info1 = *((info*)param); FILE *fin = fopen(info1.fromfile, "r+b"); FILE *fout = fopen(info1.tofile, "w+b"); int max = info1.end - info1.begin; //将文件指针分别设置在每个线程要读和写的位置 printf("begin:%d,end:%d\n",info1.begin,info1.end); char buff[1024] = {'\0'}; int len = 0; int total = 0; int copylen; int bufsize = sizeof(buff); int pos; while(true) { if( (max - total) > bufsize) { copylen= bufsize; } else { copylen = max - total; } pthread_mutex_lock(&readmutex); fseek(fin, info1.begin + total, SEEK_SET); len = fread(buff, 1,copylen, fin); pthread_mutex_unlock(&readmutex); pos = ftell(fin); if(pos < info1.begin || pos > info1.end) { printf("error pos:%d,begin:%d,end:%d!",pos,info1.begin,info1.end); } if(len <= 0) { printf("error!,len:%d,pos:%d,begin:%d,end:%d\n",len,pos,info1.begin,info1.end); break; } pthread_mutex_lock(&writemutex); fseek(fout, info1.begin + total, SEEK_SET); fwrite(buff, 1,len , fout); pthread_mutex_unlock(&writemutex); total += len; if(total == max) { printf("complete!\n"); break; } else if(total > max) { printf("copy too max!\n"); break; } //如果读入的数据大于文件总大小除线程总数则停止读入,因为每个线程要读或写的数据就等于文件总大小除线程总数 //可能会多写入一些数据,下一次写入时会覆盖多写入的数据,所以不用担心 } fclose(fin); fclose(fout); } int main(int argc, char *argv[]) { //先创建一个与文件1同样大小的文件 creat(argv[2], 0777); int size= get_size(argv[1]); truncate(argv[2], size); pthread_t pid[MAX_THREADS]; info info1[MAX_THREADS]; pthread_mutex_init(&readmutex,NULL); pthread_mutex_init(&writemutex,NULL); memset(info1, 0, sizeof(info) * MAX_THREADS); int chunk= (size + MAX_THREADS) / MAX_THREADS; //启动指定线程数的线程 for(int i = 0; i < MAX_THREADS; i++) { info1[i].fromfile = argv[1]; info1[i].tofile = argv[2]; info1[i].begin = i * chunk; info1[i].end = (i + 1) * chunk; if(info1[i].end > size) { info1[i].end = size; } printf("init begin:%d,end:%d\n",info1[i].begin,info1[i].end); pthread_create(&pid[i], NULL, threadDL, (void*)&info1[i]); } //等待线程结束 for(int j = 0; j < MAX_THREADS; j++) { //pthread_join不能用在创建进程的for循环中,否则创建第一个进程后会等待第一个进程结束后创建第二个进程 pthread_join(pid[j], NULL); } cout << "file copy success......" << endl; return 0; }
多线程拷贝通常比单线程拷贝慢。因为耗时的磁头移动操作更频繁。
但如果是RAMDISK或SSD固态硬盘当然另当别论。
When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed (the file is said to be open for “update”). However, when you switch between reading and writing, there must be an intervening fflush, fsetpos, fseek, or rewind operation. The current position can be specified for the fsetpos or fseek operation, if desired.
[解决办法]