- 论坛徽章:
- 0
|
回复 74# chenzhanyiczy
首先阐明两个概念:原子操作,可被打断(中断)和数据完整性(data integrity)。
不可被打断的操作一定是原子操作,但原子操作不一定非得不可被打断,而只是指不可被对同一数据资源的操作打断。
也就是说:原子操作只是说对本数据或资源的操作是原子的。而由其他进/线程执行的对其他数据或资源的操作是可以打断本操作的。
就像你用mutex锁定对一段数据的访问,但这并不会不被其他线程打断。
所以原子操作应该和一段数据/资源的访问相提才是有意义的。而数据完整性是指数据操作的结果和所期望的是一致的。
多线程环境下,原子操作可以保证数据完整性,否则不可以。
再来看read和write函数。所以问题就是:write函数本身是否可以保证多线程对同一文件写的数据完整性?
答案是NO。
因为内核对文件的读写事实上是按块(扇区)为单位进行的,一般每个扇区大小默认512字节,当然程序可调。
而内核的write实现并没有保证它是原子的,而只是保证它对单个扇区的读写是原子的,因为硬盘的读写就是以扇区为单位的。
这也提高了效率,否则如果write操作写的是两个不同的文件,那么如果write是原子的性能就很低。
所以只要你让多个线程同时写入一个以上字节的数据到同一文件,就可能导致数据的不完整。
假设两个线程t1,t2:- write(fd, "ab");
- write(fd, "cd");
复制代码 那么a可能写入到扇区x,b写入到扇区x+1。
c写入到扇区x,d写入到扇区x+1。
这样写入顺序就有6种:- a, b, c, d-------结果-------->cd
- a, c, b, d------结果--------->bd
- a, c, d, b------结果--------->db
- c, d, a, b------结果--------->ab
- c, a, d, b------结果--------->db
- c, a, b, d------结果--------->bd
复制代码 结果有4种:ab,db,bd,cd
这4种结果只有2种是数据完整的:ab和cd,假如你不关心写入顺序的话。其他都被写乱了。
所以数据完整性应该由调用者自己来保证。 |
|