在看muduo日志部分的时候,发现里面写文件使用的是fwrite_unlocked这个接口,之前没有见过,不过看名称就大体知道什么意思:fwrite的线程不安全版本。而且这样的接口有一个系列。因为没有用过,所以今天做了一个测试,方便以后使用。测试代码:
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#define THREAD_NUM 5
FILE *fp;
pthread_t tid[5];
const char *str = "hello world\n";
void *func(void *arg)
{
struct timeval t1;
struct timeval t2;
gettimeofday(&t1, NULL);
for (int i = 0; i < 100000; i++)
{
fwrite_unlocked(str, 1, 12, fp);
}
gettimeofday(&t2, NULL);
long us = (t2.tv_sec-t1.tv_sec)*1000000+t2.tv_usec - t1.tv_usec;
printf("%ld\n", us);
return NULL;
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("%s file_name\n", argv[0]);
return 1;
}
const char *file_name = argv[1];
fp = fopen(file_name, "ae");
for (int i = 0; i < 5; i++)
{
pthread_create(&tid[i], NULL, func, NULL);
}
for (int i = 0; i < 5; i++)
{
pthread_join(tid[i], NULL);
}
}
代码很简单,就是在几个线程里循环使用fwrite_unlocked输出,验证其线程安全性。gcc fwrite_unlock.c -o fwrite_unlock -pthread -std=gnu99 编译运行后,打开写入的文件,使用:g/hello world/d命令将正确的打印删除,会发现有很多错误的打印,例如:
rld
rld
rld
rld
o world
rld
rld
rld
o world
rld
rld
hellold
rld
rld
然后将源码中的fwrite_unlocked改为fwrite,编译执行后,删除正确的打印,会发现内容为空,说明fwrite是线程安全的。
下面的对比两次的时间:
fwrite_unlocked:
75422
80007
84918
88741
88706
fwrite
240967
250791
255675
258284
258951
看起来差别好像确实挺大的,无锁版本明显要快很多。