多线程下fwrite和write是否线程安全问题

一、代码

#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也是正常输出???

三、参考地址

https://cloud.tencent.com/developer/article/1412015

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用C语言多线程拷贝文件的例子: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #define BUFFER_SIZE 1024 struct copy_args { char *src_file; char *dst_file; int start_pos; int end_pos; }; void *copy_file(void *arg) { struct copy_args *args = (struct copy_args *)arg; FILE *src_fp = fopen(args->src_file, "rb"); FILE *dst_fp = fopen(args->dst_file, "wb"); if (src_fp == NULL || dst_fp == NULL) { printf("Failed to open file.\n"); exit(1); } fseek(src_fp, args->start_pos, SEEK_SET); int len = args->end_pos - args->start_pos + 1; char buffer[BUFFER_SIZE]; int read_len, write_len; while (len > 0 && (read_len = fread(buffer, 1, BUFFER_SIZE, src_fp)) > 0) { if (read_len > len) { read_len = len; } write_len = fwrite(buffer, 1, read_len, dst_fp); if (write_len != read_len) { printf("Failed to write file.\n"); exit(1); } len -= read_len; } fclose(src_fp); fclose(dst_fp); return NULL; } void multi_thread_copy(char *src_file, char *dst_file, int thread_num) { FILE *fp = fopen(src_file, "rb"); if (fp == NULL) { printf("Failed to open file.\n"); exit(1); } fseek(fp, 0, SEEK_END); int file_size = ftell(fp); fclose(fp); int block_size = file_size / thread_num; pthread_t *threads = (pthread_t *)malloc(thread_num * sizeof(pthread_t)); struct copy_args *args = (struct copy_args *)malloc(thread_num * sizeof(struct copy_args)); for (int i = 0; i < thread_num; i++) { args[i].src_file = src_file; args[i].dst_file = dst_file; args[i].start_pos = i * block_size; if (i == thread_num - 1) { args[i].end_pos = file_size - 1; } else { args[i].end_pos = (i + 1) * block_size - 1; } pthread_create(&threads[i], NULL, copy_file, &args[i]); } for (int i = 0; i < thread_num; i++) { pthread_join(threads[i], NULL); } free(threads); free(args); } int main() { char *src_file = "/home/XXX"; char *dst_file = "/home/dir/XXX"; int thread_num = 4; multi_thread_copy(src_file, dst_file, thread_num); printf("Copy file finished.\n"); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值