Chinaunix

标题: 多线程如何同时读写同一个文件? [打印本页]

作者: upfantasy    时间: 2013-02-19 17:39
标题: 多线程如何同时读写同一个文件?
申请了一大文件,50G,想往里面存储文件内容。通常做法是一个线程open文件,然后read,close,接着下一个线程继续写,文件被独占了,这样效率太低。有什么方法可以是多个线程同时写?
作者: linux_c_py_php    时间: 2013-02-19 17:49
1个线程即可写满磁盘util, 我做过此类项目.
作者: liuiang    时间: 2013-02-19 17:52
建议锁~~~~~~~~~~~~~~~
作者: upfantasy    时间: 2013-02-19 17:55
回复 2# linux_c_py_php
能否介绍一个方法?我的想法是把这个文件看成是一块内存,假如大小为10,在开头0存储文件A,5处存储文件B,8处存储文件C,我是想让文件A、B、C同时往这个文件里写。


   
作者: upfantasy    时间: 2013-02-19 17:56
回复 3# liuiang
锁就阻塞了,你没看清我的问题。


   
作者: freshxman    时间: 2013-02-19 18:03
提示: 作者被禁止或删除 内容自动屏蔽
作者: linux_c_py_php    时间: 2013-02-19 18:12
upfantasy 发表于 2013-02-19 17:55
回复 2# linux_c_py_php
能否介绍一个方法?我的想法是把这个文件看成是一块内存,假如大小为10,在开头0 ...


不如一个线程快, 相信党吧.
作者: windoze    时间: 2013-02-19 18:39
回复 7# linux_c_py_php

有种“磁盘”叫做FusionIO,有种设备叫做Disk Array,有种连接方式叫做Multi-Path……
相信我,想让多路读写快起来有的是办法……

作者: folklore    时间: 2013-02-19 18:46
回复 8# windoze


    求科普~~
个人认为读写一个文件的话, 好像的确不好办:(。 除非文件系统本身支持并发写。。。。
作者: folklore    时间: 2013-02-19 18:47
回复 9# folklore

只想到mmap, 这个勉强可以的样子
   
作者: linux_c_py_php    时间: 2013-02-19 19:03
mmap也快不起来, 普通硬盘就老实的单线程write吧, 用4KB/32KB一写可以明显提速.


作者: folklore    时间: 2013-02-19 19:25
回复 11# linux_c_py_php


    一直往下看贴子, 思维定势了。 这个用异步写不就可以了。 大家一起写, 等系统自动Flush(Disk Array时这个是可以多个盘同时写的)。
此外, 个人认为IO粒度自然越大越好, 而不是4K/32K。。。
作者: linux_c_py_php    时间: 2013-02-19 19:27
folklore 发表于 2013-02-19 19:25
回复 11# linux_c_py_php


真不是越大越好, 4KB明显快, 特别明显.
作者: liuiang    时间: 2013-02-19 20:25
哦,看错了。普通硬盘单线程吧,she说得对。瓶颈在io。
作者: windoze    时间: 2013-02-19 23:02
回复 9# folklore

目前所有主流的OS上的主流文件系统本身都支持并发写,关键是底下的块设备支不支持。单个普通硬盘显然没这个能力,就算是SSD其实也不行,因为绝大多数消费级的SSD都是单通道的。

但是我们有高档设备:
FusionIO:其实本质上就是很高档滴SSD,而且是多通道的,所以可以支持多路并发读写。
Disk Array:包含不止一块硬盘,做RAID可以让一个文件系统分布在不同的硬盘上,所以可以多路并发读写
Multi Path:就是让一个Disk Array通过多条线连接到主机,这样多条线可以负载分摊,进一步提高多路读写的性能。

总而言之,很多方法可以让你并发读写同一个文件而且很快,但是这些方案不是灰常贵就是灰常灰常贵,要么就是灰常灰常灰常贵……
作者: linux_c_py_php    时间: 2013-02-19 23:11
额, 怨不着公司木有这种机型, 太贵了- -..

上个项目就是写磁盘的项目, 需要在内存先按KEY缓存个1M, 等缓存堆满1M再丢给一个单线程直接做4KB一块的I/O, 杠杠的把网卡跑满了.

一开始缓存逻辑和I/O逻辑在一个线程里, 后来发现瓶颈很大, 把缓存逻辑挪到独立线程里, 通过队列交给I/O线程直接写, 这样I/O线程所有CPU都花在I/O上了, 直接high起来了.

尼玛, 多核的世界真需要好好想想了- -.
作者: FaintKnowledge    时间: 2013-02-19 23:47
回复 1# upfantasy


这种机制叫做记录锁,每个线程写多少数据就锁多少字节就可以了...
使用fcntl,得第三个参数flock结构
作者: upfantasy    时间: 2013-02-20 08:30
回复 7# linux_c_py_php

这个你说的不对,你看看迅雷下载,都是并发写的。


   
作者: morris2600    时间: 2013-02-20 10:42
xunlei是类似mmap的机制吧?
毕竟他面对的是众多普通的PC,无法对磁盘能力做过多假设
回复 18# upfantasy


   
作者: freshxman    时间: 2013-02-20 10:56
提示: 作者被禁止或删除 内容自动屏蔽
作者: linux_c_py_php    时间: 2013-02-20 11:14
upfantasy 发表于 2013-02-20 08:30
回复 7# linux_c_py_php

这个你说的不对,你看看迅雷下载,都是并发写的。


迅雷是为了网络并发下载减少下载时间, 人家分content-range下载当然快了, 磁盘那点寻道可以忽略了.
作者: hellioncu    时间: 2013-02-20 11:15
读写不同区域可以不加锁并发
作者: morris2600    时间: 2013-02-20 16:17
多线程中分别打开同一个文件?
回复 22# hellioncu


   
作者: hellioncu    时间: 2013-02-20 16:28
morris2600 发表于 2013-02-20 16:17
多线程中分别打开同一个文件?
回复 22# hellioncu


嗯,或者用pread/pwrite
作者: tansijie    时间: 2013-02-20 17:09
加个 flock 排它锁就行了,对要写的一段位置加锁,写完成就释放锁就行。
作者: upfantasy    时间: 2013-02-20 17:24
回复 24# hellioncu


我使用_sopen来做了,可以多线程同时读写同一文件,列位,觉得怎么样?


   
作者: file3    时间: 2013-02-20 21:55
硬盘的读写速度比网络传输速度大,迅雷不必考虑硬盘读写。

作者: cxytz01    时间: 2013-03-21 14:37
回复 18# upfantasy

迅雷可不可以这样,不并发写?

而是并发下载,存到一个缓冲中。另一个线程不断的扫这个缓冲,发现达到一定的阈值就写磁盘。

oracle可是这么干的。所有对数据库的修改都是放在缓冲中,然后另一个重做日志进程,将缓冲中的脏数据(改动过的)写入重做日志中。同时写进程监视这些脏缓冲,达到阈值就写数据库.
   
作者: upfantasy    时间: 2013-03-22 14:46
回复 28# cxytz01
我可以明确告诉你,迅雷下载是多线程下载,每个线程下载文件的某一块。下载之前在本地生成一个固定大小的稀释文件,下载来的文件块都是并发写到该稀释文件中。这个我已经实现了。


   
作者: cxytz01    时间: 2013-03-22 15:40
{:3_189:}
作者: tansijie    时间: 2013-03-22 16:09
有一种锁叫 lockf  试试吧。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2