一、代码
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#define USE_CLIB
#define LOOPS 1000000
#ifdef USE_CLIB
struct thr_data {
FILE *fp;
const char *data;
};
static void *write_data(void *data)
{
struct thr_data *d;
size_t len;
int i;
d = data;
len = strlen(d->data);
for (i = 0; i < LOOPS; i++) {
fwrite(d->data, 1, len, d->fp);
}
return NULL;
}
#else
struct thr_data {
int fd;
const char *data;
};
static void *write_data(void *data)
{
struct thr_data *d;
size_t len;
int i;
d = data;
len = strlen(d->data);
for (i = 0; i < LOOPS; i++) {
write(d->fd, d->data, len);
}
return NULL;
}
#endif
int main() {
#ifdef USE_CLIB
printf("using fwrite");
pthread_t t1, t2, t3;
struct thr_data d1, d2, d3;
FILE *fp = fopen("file.txt", "w");
d1.fp = d2.fp = d3.fp = fp;
d1.data = "aaa\n";
d2.data = "bbb\n";
d3.data = "ccc\n";
pthread_create(&t1, NULL, write_data, &d1);
pthread_create(&t2, NULL, write_data, &d2);
pthread_create(&t3, NULL, write_data, &d3);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
#else
printf("using write");
pthread_t t1, t2, t3;
struct thr_data d1, d2, d3;
//系统调用write则需要额外的标志位O_APPEND做追加写,来保证偏移的不重叠,实现预期的并发写入
//O_APPEND标识的使用可以让你的write把当前指针移到文件末尾,然后写出内容。并且整个过程是作为原子操作,不会产生交错现象
int fd = open("file.txt", O_WRONLY|O_TRUNC); // 非原子性操作,结果不正常
//int fd = open("file.txt", O_WRONLY|O_TRUNC|O_APPEND); // 原子性操作,结果正常
d1.fd = d2.fd = d3.fd = fd;
d1.data = "aaa\n";
d2.data = "bbb\n";
d3.data = "ccc\n";
pthread_create(&t1, NULL, write_data, &d1);
pthread_create(&t2, NULL, write_data, &d2);
pthread_create(&t3, NULL, write_data, &d3);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
#endif
}
gcc test.c -o test -lpthread 编译的时候需要链接静态库libpthread
二、结果讨论
在Linux和window下:参考文里面说fwrite是线程安全的,write在Linux下不是线程安全的。但是实际测试了下调用Linux下的write也是正常输出???