免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 9167 | 回复: 7
打印 上一主题 下一主题

[Linux] 多线程同时写一个日志文件 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-04-20 12:07 |只看该作者 |倒序浏览
一个旧项目的日志系统,没有按照常规的思路用一个线程单独写日志,而是使用多个线程同时写一个日志文件,简化如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. #include <unistd.h>
  5. static FILE* logfile;
  6. static char* logfilename = "test.log";
  7. void* thr_func(void* arg);
  8. int main()
  9. {
  10.     logfile = fopen(logfilename, "a");
  11.     //setvbuf(logfile,NULL,(int)_IOLBF,0);
  12.     int thread_num = 3;
  13.     pthread_t a[3];
  14.     printf("%ld\n",sizeof(pthread_t));
  15.     for ( int i = 0; i< thread_num ; i++ )
  16.     {
  17.         pthread_create(a+i, NULL, thr_func,NULL)
  18.     }
  19.     sleep(10);
  20.     return 0;
  21. }

  22. void* thr_func(void* arg)
  23. {
  24.     pthread_t tid = pthread_self();
  25.     fprintf(logfile,"threadid = %lu--%s\n",tid,"writing file");
  26.     fprintf(logfile,"threadid = %lu--%s\n",tid,"writing file");
  27.     fprintf(logfile,"threadid = %lu--%s\n",tid,"writing file");
  28.     return (void*)0;
  29. }
复制代码
测试结果如下:
threadid = 139753191249664--writing file
threadid = 139753191249664--writing file
threadid = 139753191249664--writing file
threadid = 139753182856960--writing file
threadid = 139753182856960--writing file
threadid = 139753182856960--writing file
threadid = 139753174464256--writing file
threadid = 139753174464256--writing file
threadid = 139753174464256--writing file
也就是看起来似乎还可以,日志内容虽然每行发生交叉,但是没有出现行内交叉。

请教如下问题:
1、fprintf需要加锁?实际测试时,若加锁,同时开启多个线程,则CPU占用异常高,应该就是抢占锁造成的,大大影响系统的效率
2、不加锁,那么如何保证一个线程的log不会被另一个线程的log打乱

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
2 [报告]
发表于 2014-04-20 14:52 |只看该作者
如果是多个线程调用,想要保证三个fprintf连续,必须加锁。或者合并三个fprintf为一个。
PS:这个demo,不加锁,难道CPU就不高了?

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
3 [报告]
发表于 2014-04-21 10:07 |只看该作者
fprintf是否有锁与glibc编译参数有关, 正确的做法应该是内存里snprintf格式化后write O_APPEND写出。

论坛徽章:
0
4 [报告]
发表于 2014-04-21 16:25 |只看该作者
同时写一个文件 都要上锁吧 ??

论坛徽章:
0
5 [报告]
发表于 2014-04-22 13:35 |只看该作者
回复 4# dspecialtwo


    嗯,理论上都应该上锁

论坛徽章:
0
6 [报告]
发表于 2014-04-22 16:46 |只看该作者
追加写一个文件,不加锁,会出现 coredump

论坛徽章:
0
7 [报告]
发表于 2014-04-22 21:48 |只看该作者
你已追加方式打开文件,本身这导致文件的操作时原子操作,不需要加锁的的吧!你也说“日志内容虽然每行发生交叉,但是没有出现行内交叉”,这就已经达到了要求了啊!不然怎么会那么巧行内不发生交叉?明显是原子操作嘛!

论坛徽章:
0
8 [报告]
发表于 2014-04-23 09:54 |只看该作者
回复 7# 栏外人27


    这个回答和楼上的回答冲突了..
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP