【问题标题】:C Thread safe locale/encoding when using sprintf and printf使用 sprintf 和 printf 时的 C 线程安全语言环境/编码
【发布时间】:2019-11-19 20:42:25
【问题描述】:

这个问题与我目前想做的事情无关,但我在阅读 sprintf() printf() 和 setlocale() 的 (GNU/Linux/ISO-C) 文档时想知道的事情。

假设问题:

想象一个多线程应用程序,它使用 printf/scanf 系列在一个线程上进行用户面对的文本输出,并在 上使用 printf/scanf 进行文件甚至网络 I/O >另一个线程。现在想象一个场景,该应用程序需要为不同类型的 I/O 使用不同的编码/语言环境。 设置语言环境/编码的方法是使用setlocale(),它在Linux Programmer's Manual 中明确标记为“MT-Unsafe”。

ISO/IEC 9899:2018 在 7.11.1.1 中有以下内容

对 setlocale 函数的调用可能会与对 setlocale 的其他调用引入数据竞争 函数或调用受当前语言环境影响的函数。实施应 表现得好像没有库函数调用 setlocale 函数。

据我所知,这使得标准 C 没有标准方法来处理前面描述的情况。 (这不涉及线程之间不必要的同步,否则不会干扰)

请注意,POSIX 指定了专门为此而设计的 uselocale() 函数。 但这不是嵌入式或多平台代码的解决方案。

问题:

  • 是否有一种可移植且不繁琐的方式来处理此类情况,而无需借助自定义库
  • 如果不是这样:从标准中省略此类功能的原因可能是什么

TL;DR: 如何处理多线程编码(POSIX 之外)?

【问题讨论】:

    标签: c multithreading encoding printf locale


    【解决方案1】:

    一旦程序变为多线程,您就不能在程序中安全地使用setlocale。如果您需要多个语言环境,则需要 newlocale/uselocale API 用于线程本地或一流的语言环境对象,而不是 setlocale。

    【讨论】:

      【解决方案2】:

      也许通过使用或多或少的标准互斥锁?例如。如How to Use C Mutex Lock Examples for Linux Thread Synchronization 所述:

      简介

      我们雇用pthread.h。线程管理将是:

      ...
      pthread_t tid[2];
      pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
      pthread_join(tid[0], NULL);
      pthread_join(tid[1], NULL);
      ...
      

      一个互斥体被初始化,然后通过调用以下两个函数来获得一个锁:

      int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
      int pthread_mutex_lock(pthread_mutex_t *mutex);
      

      可以通过调用以下函数来解锁和销毁互斥锁​​:

      int pthread_mutex_unlock(pthread_mutex_t *mutex);
      int pthread_mutex_destroy(pthread_mutex_t *mutex);
      

      实例

      让我们看一段使用互斥锁进行线程同步的代码:

      #include<stdio.h>
      #include<string.h>
      #include<pthread.h>
      #include<stdlib.h>
      #include<unistd.h>
      
      pthread_t tid[2];
      int counter;
      pthread_mutex_t lock;
      
      void* doSomeThing(void *arg)
      {
          pthread_mutex_lock(&lock);
      
          unsigned long i = 0;
          counter += 1;
          printf("\n Job %d started\n", counter);
      
          for(i=0; i<(0xFFFFFFFF);i++);
      
          printf("\n Job %d finished\n", counter);
      
          pthread_mutex_unlock(&lock);
      
          return NULL;
      }
      
      int main(void)
      {
          int i = 0;
          int err;
      
          if (pthread_mutex_init(&lock, NULL) != 0)
          {
              printf("\n mutex init failed\n");
              return 1;
          }
      
          while(i < 2)
          {
              err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
              if (err != 0)
                  printf("\ncan't create thread :[%s]", strerror(err));
              i++;
          }
      
          pthread_join(tid[0], NULL);
          pthread_join(tid[1], NULL);
          pthread_mutex_destroy(&lock);
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多