多线程写文件的问题

hunterize 2007-12-03 05:01:19
创建一个简单的mfc dialog对话框程序,添加一个按钮,启动两个线程写同一个文件,关键的代码如下
1、

#define M 1024*1024

void CMultithreadMFCDlg::OnButton1()
{
HANDLE hd1;
HANDLE hd2;

DWORD hdid1;
DWORD hdid2;

hd1 = CreateThread(NULL,0,Fun1,NULL,0,&hdid1);
hd2 = CreateThread(NULL,0,Fun2,NULL,0,&hdid2);
}


DWORD WINAPI Fun1(LPVOID stream)
{
FILE *sstream = fopen("a.txt","a+");
BYTE *tmp = new BYTE[M];
memset(tmp,97,M);
fwrite(tmp,sizeof(char),M,(FILE *)sstream);
return 1;
}

DWORD WINAPI Fun2(LPVOID stream)
{
FILE *sstream = fopen("a.txt","a+");
BYTE *tmp = new BYTE[M];
memset(tmp,98,M);
fwrite(tmp,sizeof(char),M,(FILE *)sstream);
return 1;
}
...
问题是这样操作的时候写的文件大小每次都不同,而且都没有到2m

2、
如果换一种方式,两个线程往同一个file handle里写数据就没有问题
CMultithreadMFCDlg::CMultithreadMFCDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMultithreadMFCDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CMultithreadMFCDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
this->m_fStream = fopen("a.txt","a+");
}

void CMultithreadMFCDlg::OnButton1()
{
HANDLE hd1;
HANDLE hd2;

DWORD hdid1;
DWORD hdid2;

hd1 = CreateThread(NULL,0,Fun1,this->m_fStream,0,&hdid1);
hd2 = CreateThread(NULL,0,Fun2,this->m_fStream,0,&hdid2);
}

DWORD WINAPI Fun1(LPVOID stream)
{
BYTE *tmp = new BYTE[M];
memset(tmp,97,M);
fwrite(tmp,sizeof(char),M,(FILE *)stream);
return 1;
}

DWORD WINAPI Fun2(LPVOID stream)
{
BYTE *tmp = new BYTE[M];
memset(tmp,98,M);
fwrite(tmp,sizeof(char),M,(FILE *)stream);
return 1;
}
这样的话每次写文件大小为2m,没有什么错误

这两种方式有什么不同吗?创建两个file object分别操作和创建一个file object操作不同的handle会产生这个差别吗?



...全文
468 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
既然是线程安全的,还要同步干什么。
线程安全和同步是什么关系。
不是用同步来保持线程安全操作吗
hunterize 2007-12-05
  • 打赏
  • 举报
回复
不是在讨论用什么方法,而是为什么会出现这样的情况
forwtl 2007-12-05
  • 打赏
  • 举报
回复
这个跟线程同步应该没关系,fwrite本身是线程安全的,这两种方法的到的结果文件内容都是aaaaaaa......bbbbbb.....
只不过第一种方法似乎丢了一些数据

------------------------------------------------------
fwrite本身是线程安全的

只要不是对全局变量进行了操作,所有的函数,都是线程安全的。

但,只要是你写多线程,就要尽量处理好 临界代码 。否则,就算是你调用 线程安全 的函数,也可能造成不安全的因素。

forwtl 2007-12-05
  • 打赏
  • 举报
回复
问题是这样操作的时候写的文件大小每次都不同,


你试试这样查找问题:

方法一: //加入代码
DWORD WINAPI Fun1(LPVOID stream)
{
//fpos_t pos;
FILE *sstream = fopen("a.txt","a+");
BYTE *tmp = new BYTE[M];
memset(tmp,97,M);
fwrite(tmp,sizeof(char),M,(FILE *)sstream);

//fgetpos( sstream, &pos )
//TRACE( pos );

return 1;
}


方法二:
DWORD WINAPI Fun1(LPVOID stream)
{
//fpos_t pos;
FILE *sstream = fopen("a.txt","a+");
BYTE *tmp = new BYTE[M];
memset(tmp,97,M);
fwrite(tmp,sizeof(char),M,(FILE *)sstream);
//fflush( sstream );
return 1;
}

猜测问题是在这里:

fwrite 是会改变当前文件定位的,就是 offset。而 offset 是和 sstream file handle 相关的。

这也就是

2、
如果换一种方式,两个线程往同一个file handle里写数据就没有问题

没有问题的原因。
hunterize 2007-12-04
  • 打赏
  • 举报
回复
顶了,听听大家的意见
tccqs 2007-12-04
  • 打赏
  • 举报
回复
up and mark!!
forwtl 2007-12-04
  • 打赏
  • 举报
回复
为什么一定要用多线程呢,重叠 IO 多好。

我的问题,都没人睬,55555555。
http://topic.csdn.net/u/20071204/14/46a5b436-5c23-4cd3-9845-74124e890866.html
hunterize 2007-12-04
  • 打赏
  • 举报
回复
to crearo
第一个方法和第二个都是调用了fwrite,为什么第一个文件没保护呢?
abzhang2 2007-12-04
  • 打赏
  • 举报
回复
同步内容
工布之者 2007-12-04
  • 打赏
  • 举报
回复
up
铜板 2007-12-04
  • 打赏
  • 举报
回复
第一个,文件没保护多线程操作肯定出问题。
第二个,fwrite操作时候受了一定的保护,可能fwrite操作是原子操作吧,因为只是一次把数据全写入。觉得也应当肯定也是不安全的。。
最好用CreateFile独享模式,比较安全点
YangDa 2007-12-04
  • 打赏
  • 举报
回复
顶了看高人回复
hunterize 2007-12-04
  • 打赏
  • 举报
回复
顶起,等待高人指点
hunterize 2007-12-03
  • 打赏
  • 举报
回复
这个跟线程同步应该没关系,fwrite本身是线程安全的,这两种方法的到的结果文件内容都是aaaaaaa......bbbbbb.....
只不过第一种方法似乎丢了一些数据
zoulie 2007-12-03
  • 打赏
  • 举报
回复
线程同步~

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧