为了账号安全,请及时绑定邮箱和手机立即绑定

线程安全与可重入

/ 猿问

线程安全与可重入

撒科打诨 2019-12-09 15:00:11

最近,我问了一个问题,标题为“ malloc线程安全吗?” ,然后我问:“ malloc是否可重入?”


我的印象是所有重入者都是线程安全的。


这个假设错了吗?


查看完整描述

3 回答

?
LEATH

函数可以是可重入的,线程安全的,或者两者均可。


维基百科上有关线程安全性和可重入性的文章非常值得一读。这里有一些引用:


在以下情况下,函数是线程安全的:


它仅以确保多个线程同时安全执行的方式操作共享数据结构。


在以下情况下,函数是可重入的:


它可以在执行过程中的任何时候中断,然后在之前的调用完成执行之前安全地再次调用(“重新输入”)。


作为可能重新进入的示例,维基百科给出了一个设计为由系统中断调用的函数的示例:假设当另一个中断发生时该函数已经在运行。但是不要仅仅因为您不使用系统中断进行编码就认为您是安全的:如果使用回调或递归函数,则在单线程程序中可能会遇到重入问题。


避免混淆的关键是可重入仅指一个正在执行的线程。从不存在多任务操作系统的时代开始就是一个概念。


例子


(从维基百科的文章稍作修改)


示例1:不是线程安全的,不是可重入的


/* As this function uses a non-const global variable without

   any precaution, it is neither reentrant nor thread-safe. */


int t;


void swap(int *x, int *y)

{

    t = *x;

    *x = *y;

    *y = t;

}

示例2:线程安全,不可重入


/* We use a thread local variable: the function is now

   thread-safe but still not reentrant (within the

   same thread). */


__thread int t;


void swap(int *x, int *y)

{

    t = *x;

    *x = *y;

    *y = t;

}

示例3:不是线程安全的,可重入


/* We save the global state in a local variable and we restore

   it at the end of the function.  The function is now reentrant

   but it is not thread safe. */


int t;


void swap(int *x, int *y)

{

    int s;

    s = t;

    t = *x;

    *x = *y;

    *y = t;

    t = s;

}

示例4:线程安全,可重入


/* We use a local variable: the function is now

   thread-safe and reentrant, we have ascended to

   higher plane of existence.  */


void swap(int *x, int *y)

{

    int t;

    t = *x;

    *x = *y;

    *y = t;

}


查看完整回答
反对 回复 2019-12-09
?
慕函数4003404

这取决于定义。例如,Qt使用以下内容:


即使调用使用共享数据,也可以从多个线程同时调用线程安全*函数,因为对共享数据的所有引用都已序列化。


一个可重入函数也可以从多个线程同时调用,但只有当每个调用使用自己的数据。


因此,线程安全函数始终是可重入的,但是重入函数并不总是线程安全的。


通过扩展,如果可以从多个线程安全地调用其成员函数,则该类称为可重入的,只要每个线程使用该类的不同实例即可。如果可以从多个线程安全地调用其成员函数,则该类是线程安全的,即使所有线程都使用该类的相同实例也是如此。


但他们也警告:


注意:多线程域中的术语尚未完全标准化。POSIX使用可重入和线程安全的定义,这些定义对其C API有所不同。当将其他面向对象的C ++类库与Qt一起使用时,请确保理解定义。


查看完整回答
反对 回复 2019-12-09

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信