Both the C Runtime Library and the Standard C++ Library provide support for changing the locale of your program. This topic discusses issues that arise when using the locale functionality of both libraries in a multithreaded application.
Remarks
With the C Runtime Library, you can create multithreaded applications using the _beginthread and _beginthreadex functions. This topic only covers multithreaded applications created using these functions. For more information, see
To change the locale using the C Runtime Library, use the _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
in that thread. Conversely, calling _configthreadlocale(_DISABLE_PER_THREAD_LOCALE)
will cause that thread to use the global locale, and any call to
To change the locale using the C++ Runtime Library, use the
![]() |
---|
Calling |
The following examples show how to use the
Calling setlocale in a Thread that Has Enabled Per Thread Locale
Example
In this example, the main thread spawns two child threads. The first thread, Thread A, enables per-thread locale by calling _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
. The second thread, Thread B, as well as the main thread, do not enable per-thread locale. Thread A then proceeds to change the locale using the
Since Thread A has per-thread locale enabled, only the C Runtime Library functions in Thread A start using the "french" locale. The C Runtime Library functions in Thread B and in the main thread continue to use the "C" locale. Also, since
В | ![]() |
---|---|
// multithread_locale_1.cpp // compile with: /EHsc /MD #include <clocale> #include <cstdio> #include <locale> #include <process.h> #include <windows.h> #define NUM_THREADS 2 using namespace std; unsigned __stdcall RunThreadA(void *params); unsigned __stdcall RunThreadB(void *params); BOOL localeSet = FALSE; HANDLE printMutex = CreateMutex(NULL, FALSE, NULL); int main() { HANDLE threads[NUM_THREADS]; unsigned aID; threads[0] = (HANDLE)_beginthreadex( NULL, 0, RunThreadA, NULL, 0, &aID); unsigned bID; threads[1] = (HANDLE)_beginthreadex( NULL, 0, RunThreadB, NULL, 0, &bID); WaitForMultipleObjects(2, threads, TRUE, INFINITE); printf_s("[Thread main] Per-thread locale is NOT enabled.\n"); printf_s("[Thread main] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread main] locale::global is set to \"%s\"\n", locale().name().c_str()); CloseHandle(threads[0]); CloseHandle(threads[1]); CloseHandle(printMutex); return 0; } unsigned __stdcall RunThreadA(void *params) { _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); setlocale(LC_ALL, "french"); localeSet = TRUE; WaitForSingleObject(printMutex, INFINITE); printf_s("[Thread A] Per-thread locale is enabled.\n"); printf_s("[Thread A] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread A] locale::global is set to \"%s\"\n\n", locale().name().c_str()); ReleaseMutex(printMutex); return 1; } unsigned __stdcall RunThreadB(void *params) { while (!localeSet) Sleep(100); WaitForSingleObject(printMutex, INFINITE); printf_s("[Thread B] Per-thread locale is NOT enabled.\n"); printf_s("[Thread B] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread B] locale::global is set to \"%s\"\n\n", locale().name().c_str()); ReleaseMutex(printMutex); return 1; } |
Output
В | |
---|---|
[Thread A] Per-thread locale is enabled. [Thread A] CRT locale is set to "French_France.1252" [Thread A] locale::global is set to "C" [Thread B] Per-thread locale is NOT enabled. [Thread B] CRT locale is set to "C" [Thread B] locale::global is set to "C" [Thread main] Per-thread locale is NOT enabled. [Thread main] CRT locale is set to "C" [Thread main] locale::global is set to "C" |
In this example, the main thread spawns two child threads. The first thread, Thread A, enables per-thread locale by calling _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
. The second thread, Thread B, as well as the main thread, do not enable per-thread locale. Thread A then proceeds to change the locale using the
Since Thread A has per-thread locale enabled, only the C Runtime Library functions in Thread A start using the "french" locale. The C Runtime Library functions in Thread B and in the main thread continue to use the "C" locale. However, since the
В | ![]() |
---|---|
// multithread_locale_2.cpp // compile with: /EHsc /MD #include <clocale> #include <cstdio> #include <locale> #include <process.h> #include <windows.h> #define NUM_THREADS 2 using namespace std; unsigned __stdcall RunThreadA(void *params); unsigned __stdcall RunThreadB(void *params); BOOL localeSet = FALSE; HANDLE printMutex = CreateMutex(NULL, FALSE, NULL); int main() { HANDLE threads[NUM_THREADS]; unsigned aID; threads[0] = (HANDLE)_beginthreadex( NULL, 0, RunThreadA, NULL, 0, &aID); unsigned bID; threads[1] = (HANDLE)_beginthreadex( NULL, 0, RunThreadB, NULL, 0, &bID); WaitForMultipleObjects(2, threads, TRUE, INFINITE); printf_s("[Thread main] Per-thread locale is NOT enabled.\n"); printf_s("[Thread main] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread main] locale::global is set to \"%s\"\n", locale().name().c_str()); CloseHandle(threads[0]); CloseHandle(threads[1]); CloseHandle(printMutex); return 0; } unsigned __stdcall RunThreadA(void *params) { _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); locale::global(locale("french")); localeSet = TRUE; WaitForSingleObject(printMutex, INFINITE); printf_s("[Thread A] Per-thread locale is enabled.\n"); printf_s("[Thread A] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread A] locale::global is set to \"%s\"\n\n", locale().name().c_str()); ReleaseMutex(printMutex); return 1; } unsigned __stdcall RunThreadB(void *params) { while (!localeSet) Sleep(100); WaitForSingleObject(printMutex, INFINITE); printf_s("[Thread B] Per-thread locale is NOT enabled.\n"); printf_s("[Thread B] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread B] locale::global is set to \"%s\"\n\n", locale().name().c_str()); ReleaseMutex(printMutex); return 1; } |
Output
В | |
---|---|
[Thread A] Per-thread locale is enabled. [Thread A] CRT locale is set to "French_France.1252" [Thread A] locale::global is set to "French_France.1252" [Thread B] Per-thread locale is NOT enabled. [Thread B] CRT locale is set to "C" [Thread B] locale::global is set to "French_France.1252" [Thread main] Per-thread locale is NOT enabled. [Thread main] CRT locale is set to "C" [Thread main] locale::global is set to "French_France.1252" |
In this example, the main thread spawns two child threads. The first thread, Thread A, enables per-thread locale by calling _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
. The second thread, Thread B, as well as the main thread, do not enable per-thread locale. Thread B then proceeds to change the locale using the
Since Thread B does not have per-thread locale enabled, the C Runtime Library functions in Thread B and in the main thread start using the "french" locale. The C Runtime Library functions in Thread A continue to use the "C" locale because Thread A has per-thread locale enabled. Also, since
В | ![]() |
---|---|
// multithread_locale_3.cpp // compile with: /EHsc /MD #include <clocale> #include <cstdio> #include <locale> #include <process.h> #include <windows.h> #define NUM_THREADS 2 using namespace std; unsigned __stdcall RunThreadA(void *params); unsigned __stdcall RunThreadB(void *params); BOOL localeSet = FALSE; HANDLE printMutex = CreateMutex(NULL, FALSE, NULL); int main() { HANDLE threads[NUM_THREADS]; unsigned aID; threads[0] = (HANDLE)_beginthreadex( NULL, 0, RunThreadA, NULL, 0, &aID); unsigned bID; threads[1] = (HANDLE)_beginthreadex( NULL, 0, RunThreadB, NULL, 0, &bID); WaitForMultipleObjects(2, threads, TRUE, INFINITE); printf_s("[Thread main] Per-thread locale is NOT enabled.\n"); printf_s("[Thread main] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread main] locale::global is set to \"%s\"\n", locale().name().c_str()); CloseHandle(threads[0]); CloseHandle(threads[1]); CloseHandle(printMutex); return 0; } unsigned __stdcall RunThreadA(void *params) { _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); while (!localeSet) Sleep(100); WaitForSingleObject(printMutex, INFINITE); printf_s("[Thread A] Per-thread locale is enabled.\n"); printf_s("[Thread A] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread A] locale::global is set to \"%s\"\n\n", locale().name().c_str()); ReleaseMutex(printMutex); return 1; } unsigned __stdcall RunThreadB(void *params) { setlocale(LC_ALL, "french"); localeSet = TRUE; WaitForSingleObject(printMutex, INFINITE); printf_s("[Thread B] Per-thread locale is NOT enabled.\n"); printf_s("[Thread B] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread B] locale::global is set to \"%s\"\n\n", locale().name().c_str()); ReleaseMutex(printMutex); return 1; } |
Output
В | |
---|---|
[Thread B] Per-thread locale is NOT enabled. [Thread B] CRT locale is set to "French_France.1252" [Thread B] locale::global is set to "C" [Thread A] Per-thread locale is enabled. [Thread A] CRT locale is set to "C" [Thread A] locale::global is set to "C" [Thread main] Per-thread locale is NOT enabled. [Thread main] CRT locale is set to "French_France.1252" [Thread main] locale::global is set to "C" |
In this example, the main thread spawns two child threads. The first thread, Thread A, enables per-thread locale by calling _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
. The second thread, Thread B, as well as the main thread, do not enable per-thread locale. Thread B then proceeds to change the locale using the
Since Thread B does not have per-thread locale enabled, the C Runtime Library functions in Thread B and in the main thread start using the "french" locale. The C Runtime Library functions in Thread A continue to use the "C" locale because Thread A has per-thread locale enabled. However, since the
В | ![]() |
---|---|
// multithread_locale_4.cpp // compile with: /EHsc /MD #include <clocale> #include <cstdio> #include <locale> #include <process.h> #include <windows.h> #define NUM_THREADS 2 using namespace std; unsigned __stdcall RunThreadA(void *params); unsigned __stdcall RunThreadB(void *params); BOOL localeSet = FALSE; HANDLE printMutex = CreateMutex(NULL, FALSE, NULL); int main() { HANDLE threads[NUM_THREADS]; unsigned aID; threads[0] = (HANDLE)_beginthreadex( NULL, 0, RunThreadA, NULL, 0, &aID); unsigned bID; threads[1] = (HANDLE)_beginthreadex( NULL, 0, RunThreadB, NULL, 0, &bID); WaitForMultipleObjects(2, threads, TRUE, INFINITE); printf_s("[Thread main] Per-thread locale is NOT enabled.\n"); printf_s("[Thread main] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread main] locale::global is set to \"%s\"\n", locale().name().c_str()); CloseHandle(threads[0]); CloseHandle(threads[1]); CloseHandle(printMutex); return 0; } unsigned __stdcall RunThreadA(void *params) { _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); while (!localeSet) Sleep(100); WaitForSingleObject(printMutex, INFINITE); printf_s("[Thread A] Per-thread locale is enabled.\n"); printf_s("[Thread A] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread A] locale::global is set to \"%s\"\n\n", locale().name().c_str()); ReleaseMutex(printMutex); return 1; } unsigned __stdcall RunThreadB(void *params) { locale::global(locale("french")); localeSet = TRUE; WaitForSingleObject(printMutex, INFINITE); printf_s("[Thread B] Per-thread locale is NOT enabled.\n"); printf_s("[Thread B] CRT locale is set to \"%s\"\n", setlocale(LC_ALL, NULL)); printf_s("[Thread B] locale::global is set to \"%s\"\n\n", locale().name().c_str()); ReleaseMutex(printMutex); return 1; } |
Output
В | |
---|---|
[Thread B] Per-thread locale is NOT enabled. [Thread B] CRT locale is set to "French_France.1252" [Thread B] locale::global is set to "French_France.1252" [Thread A] Per-thread locale is enabled. [Thread A] CRT locale is set to "C" [Thread A] locale::global is set to "French_France.1252" [Thread main] Per-thread locale is NOT enabled. [Thread main] CRT locale is set to "French_France.1252" [Thread main] locale::global is set to "French_France.1252" |
Calling locale::global in a Thread that Has Enabled Per Thread Locale
Calling setlocale in a Thread that Has Not Enabled Per Thread Locale
Calling locale::global in a Thread that Has Not Enabled Per Thread Locale
See Also
Reference
Concepts
Multithreading