b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

可重入性和线程安全性

电脑杂谈  发布时间:2020-06-15 23:17:59  来源:网络整理

禁止跨线程调用安全_c跨线程调用窗体控件_wpf 跨线程访问控件

可重入性和线程安全性都与该函数如何处理资源有关. 但是,它们是不同的:

重入函数既不会在连续调用中存储静态数据,也不会返回指向静态数据的指针. 对于此类功能,调用者将提供该功能所需的所有数据,例如指向任何工作区的指针. 这意味着对一个函数的多个并发调用不会互相干扰.

注意: 可重入函数不能调用非可重入函数.

线程安全功能使用锁来保护共享资源,以防止并发访问它们. 线程安全仅涉及功能的实现方式,而不涉及其外部接口. 在C语言中,局部变量在堆栈上动态分配. 因此,任何不使用静态数据或其他共享资源的函数通常都是线程安全的.

在ARM库中,函数可能是线程安全的,如下所示:

某些函数永远都不是线程安全的,例如setlocale()

某些函数本质上是线程安全的,例如memcpy()

通过实现_mutex_ *函数,可以使某些函数(例如malloc())成为线程安全的

其他函数仅在传递适当的参数(例如tmpnam())时才是线程安全的.

如果应用程序以隐藏方式(例如,使用语言助手功能)使用ARM库,则可能会出现线程问题.

线程安全功能

calloc(),

free(),

malloc(),

realloc()

如果实现了_mutex_ *函数,则堆函数是线程安全的.

在所有线程之间共享一个堆,并使用互斥锁避免在并发访问期间破坏数据. 每个堆实现负责其自己的锁定. 如果您提供自己的分配器,它也必须锁定. 这样,它可以执行精细锁定(如果需要),而不是简单地使用单个互斥对象保护整个堆(扩展锁定).

__ alloca(),

__ alloca_finish(),

__ alloca_init(),

__ alloca_initialize()

如果实现了_mutex_ *函数,则alloca函数是线程安全的.

每个线程的alloca状态包含在__user_perthread_libspace块中. 这意味着多个线程不会冲突.

请注意,alloca函数也使用堆. 但是堆函数都是线程安全的.

wpf 跨线程访问控件_c跨线程调用窗体控件_禁止跨线程调用安全

abort(),

raise(),

signal(),

fenv.h

ARM信号处理功能和FP异常捕获是线程安全的.

信号处理程序和FP捕获设置是整个过程中的全局设置,并受锁保护. 这样,即使多个线程同时调用signal()或fenv.h函数,数据也不会被损坏. 但是请注意,该调用会影响所有线程,而不仅是调用线程.

clearerr(),fclose(),

feof(),ferror(),fflush(),

fgetc(),fgetpos(),fgets(),

fopen(),fputc(),fputs(),

fread(),freopen(),fseek(),

fsetpos(),ftell(),fwrite(),

getc(),getchar(),gets(),

perror(),putc(),putchar(),

puts(),rewind(),setbuf(),

setvbuf(),tmpfile(),tmpnam(),

ungetc()

如果实现了_mutex_ *函数,则stdio库是线程安全的.

每个单独的流都受锁保护,因此两个线程可以打开并单独使用自己的stdio流,而不会互相干扰.

如果两个线程必须读取或写入同一流,则fgetc()和fputc()级别的锁定可以防止数据损坏,但是,每个线程的单个字符输出可能会交叉,因此很容易引起混乱.

请注意,tmpnam()也包含一个静态缓冲区,但仅在参数为NULL时使用. 为了确保tmpnam()的使用是线程安全的,您应该提供自己的缓冲区空间.

fprintf(),printf(),

vfprintf(),vprintf(),fscanf(),

scanf()

wpf 跨线程访问控件_禁止跨线程调用安全_c跨线程调用窗体控件

使用这些功能时:

标准C printf()和scanf()函数使用stdio,因此是线程安全的.

如果在多线程程序中调用标准C printf(),则其语言环境可能会更改.

clock()clock()包含程序静态数据,该数据在启动时写入一次,以后只能读取. 因此,clock()是线程安全的,但前提是在初始化库时没有其他线程在运行.

errno()

errno是线程安全的.

每个线程在__user_perthread_libspace块中存储自己的errno. 这意味着每个线程可以单独调用errno设置函数,然后检查errno,而不必担心会受到其他线程的影响.

atexit()

atexit()维护的退出函数列表是该进程的全局变量,并受锁保护.

在最坏的情况下,如果多个线程调用atexit(),则无法保证退出函数的调用顺序.

abs(),acos(),asin(),atan(),

atan2(),atof(),atol(),atoi(),

bsearch(),ceil(),cos(),

cosh(),difftime(),div(),

exp()禁止跨线程调用安全,fabs(),floor(),

fmod(),frexp(),labs(),

ldexp(),ldiv(),log(),

log10(),memchr(),memcmp(),

memcpy(),memmove(),memset(),

mktime(),modf(),pow()禁止跨线程调用安全

qsort(),sin(),sinh(),

sqrt(),strcat(),strchr(),

strcmp(),strcpy(),strcspn(),

strlcat(),strlcpy(),strlen(),

wpf 跨线程访问控件_c跨线程调用窗体控件_禁止跨线程调用安全

strncat(),strncmp(),strncpy(),

strpbrk(),strrchr(),strspn(),

strstr(),strxfrm(),tan(),tanh()

这些函数本质上是线程安全的.

longjmp(),setjmp()

尽管setjmp()和longjmp()将数据保存在__user_libspace中,但它们都调用了线程安全的__alloca_ *函数.

remove(),rename(),time()

这些功能使用中断与ARM调试环境进行通信. 通常,必须针对实际应用重新实现这些功能.

snprintf(),sprintf(),

vsnprintf(),vsprintf(),sscanf(),

isalnum(),isalpha(),iscntrl(),

isdigit(),isgraph(),islower(),

isprint(),ispunct(),isspace(),

isupper(),isxdigit(),tolower(),

toupper(),strcoll(),strtod(),

strtol(),strtoul(),strftime()

使用这些函数时,这些基于字符串的函数将读取语言环境. 通常,它们是线程安全的. 但是,如果您在会话期间更改语言环境,则必须确保这些功能不受影响.

基于字符串的函数不依赖于stdio库,例如sprintf()和sscanf().

函数stdin,stdout,stderr是线程安全的.

FP状态字

FP状态字可以在多线程环境(甚至软件浮点)中安全使用. 其中,每个线程的状态字都存储在其自己的__user_perthread_libspace块中.

注意

请注意,在硬件浮点中,FP状态字存储在VFP寄存器中. 在这种情况下,线程切换机制必须为每个线程保留该寄存器的单独副本.

非线程安全功能

禁止跨线程调用安全_c跨线程调用窗体控件_wpf 跨线程访问控件

setlocale()

语言环境设置是所有线程的全局设置,并且不受锁保护. 如果两个线程调用setlocale(),则可能会发生数据损坏. 另外,许多其他函数读取当前的语言环境设置,例如strtod()和sprintf(). 因此,如果一个线程同时调用setlocale(),而另一个线程同时调用此函数,则可能会产生意外的结果.

ARM建议您选择所需的语言环境,然后调用一次setlocale()对其进行初始化. 应该在程序中创建任何其他线程之前完成此操作,以便任意数量的线程可以同时读取语言环境设置而不会互相干扰.

请注意,localeconv()并非线程安全的. 而是使用指向用户提供的缓冲区的指针来调用ARM函数_get_lconv().

asctime(),localtime(),

strtok()

这些函数不是线程安全的. 每个函数都包含一个静态缓冲区,在调用该函数与随后使用其返回值之间,其他线程可能会覆盖该缓冲区.

ARM提供可重入版本_asctime_r(),_ localtime_r()和_strtok_r(). ARM建议您改用这些功能以确保安全.

注意

这些可重入版本使用一些附加参数. _asctime_r()使用的附加参数是指向要在其中写入输出字符串的缓冲区的指针. _localtime_r()使用的附加参数是指向要写入结果的结构tm的指针. _strtok_r()使用的附加参数也是指向下一个标记的char指针的指针.

gamma()[1],lgamma()这些扩展的mathlib函数使用全局变量_signgam,因此不是线程安全的.

mbrlen(),mbsrtowcs(),

mbrtowc(),wcrtomb(),

wcsrtombs()

stdlib.h中定义的C89多字节转换函数(例如mblen()和mbtowc())不是线程安全的,因为它们包含在所有线程之间共享且未锁定的内部静态状态.

但是,wchar.h中定义的扩展的可重新启动版本(例如mbrtowc()和wcrtomb())是线程安全的,但前提是您必须传递指向自己的mbstate_t对象的指针. 如果要在处理多字节字符串时确保线程安全,则这些函数只能使用非NULL mbstate_t *参数.

exit()

即使提供了基本的_sys_exit()(实际上终止了所有线程)的实现,也不要在多线程程序中调用exit().

在这种情况下,exit()在调用_sys_exit()之前执行清除操作,因此它将中断其他线程.

rand(),srand()

这些功能保留全局和不受保护的内部状态. 这意味着rand()调用永远都不是线程安全的.

ARM建议您使用自己的锁来确保一次只有一个线程调用rand(),例如,通过定义$ Sub $$ rand()(如果要避免代码更改).

或者,您也可以执行以下操作之一:

提供您自己的随机数,该可能具有多个独立的实例

强制性要求只有一个线程需要生成一个随机数.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/tongxinshuyu/article-246734-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...