多线程追加文件,不加锁,会出现什么情况 ?

线程1追加111111111,线程2追加22222222222,一直到线程9追加9999999999, 最后生成的内容会出现,113478933322…
关注者
161
被浏览
51,569

11 个回答

无定义。

顺便用这个问题来回答一下这个问题(

linux/sem.h和sys/sem.h有什么区别? - in nek 的回答

)下有人问我的问题:什么叫基于语义来进行编程?

其实这句话完整说应该是:要基于“自然语义”来进行编程。

我是软件架构师,我考虑的问题大部分时候是让自己的软件活得更久。软件面对各种各样的变化,软件换场景了,硬件升级了,操作系统升级了,换操作系统类型了,换开发库了,换数据库了……不一而足,怎么样让软件活下来?我的方法是,“基于语义进行编程”。

语义是一句话的自然的,表面的意思。大部分软件,都是解决人的问题,所以它的接口发展受人的思维所控制,这种接口上的控制,进一步会控制到内部的数据流,脱离人的思维去构造人脑逻辑之外的计算机逻辑,会增加接口发展的风险,会很快造成构架的破坏。

另一方面说,现在的计算机编程,通常都是要采用敏捷迭代的方式完成的。所以,一个定义(变量,函数)的含义,是这个定义的名称(以及其自然语义)决定的,而不是这个定义当前如何使用决定的。我的log函数现在实现成了printf,不表示你可以用printf来代替log,因为这个函数未来可以变更为写入数据库。

推广开去,比如现实中,一个网卡有一个mac,有两个mac的叫聚合,在OS的自然定义中,人们认为两个mac聚合是两张网卡的聚合。但你非要作死,在定义网卡的时候,非要用一个数组来放多个mac,后面配合的时候,网卡子系统不修理你,外部互联的子系统也会修理你,因为没有人会按你这样的考虑来构造其他系统,你就死得很快。

你要写日志,就用log()函数,你要打印输出,就用printf函数,你不能用printf来写日志,我知道你也能跑,但printf的语义不是日志,到你真要打印的时候,这两个函数会给你带来麻烦,你更不要用assert()等来当作日志输出(临时程序我不管,我说的是严肃的程序),这就叫基于语义编程,而不是基于逻辑(能跑)来编程。

有人问我malloc(0)返回什么,我说你去查手册,他说,他不用查,他试过了,是一个非0的指针,我说So what?你在几个平台上验证过?你看看man,人家是这样说的:

If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free()

你要基于这个来写程序,这样的程序才能活得长远。

理解这一点,也许更容易理解我前面的“无定义”是什么意思了。

同一个进程内 , 针对同一个 FILE* 操作 (比如fwrite), 是 线程安全 的. 当然这只在POSIX兼容的系统上成立, Windows上的FILE*的操作并不是线程安全的.

gcc.gnu.org/onlinedocs/

As an example, the POSIX standard requires that C stdio FILE* operations are atomic. POSIX-conforming C libraries (e.g, on Solaris and GNU/Linux) have an internal mutex to serialize operations on FILE*s. However, you still need to not do stupid things like calling fclose(fs) in one thread followed by an access of fs in another.

PS:

我就在Linux上使用这一特性来记录log.