原子属性和非原子属性有什么区别?

2020/10/26 13:32 · ios ·  · 0评论

什么atomicnonatomic财产申报是什么意思?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;

这三个之间的操作区别是什么?

最后两个是相同的;“原子”是默认的行为(注意,它实际上不是一个关键字,它仅由没有规定nonatomic-atomic在最近版本的LLVM /铛加入关键字)。

假定您正在@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@一起为止的转换的前提下才能实现的,那么原子与非原子就可以改变生成的代码。如果您正在编写自己的setter / getter,则原子/非原子/保留/分配/复制仅是建议性的。(注意:@synthesize现在是LLVM的最新版本中的默认行为。也无需声明实例变量;它们也将自动合成,并且将_在其名称前添加前缀以防止意外的直接访问)。

使用“ atomic”,合成的setter / getter将确保始终从getter返回或由setter设置整个值,而不管任何其他线程上的setter活动如何。也就是说,如果线程A在getter的中间,而线程B在调用setter时,则实际的可行值(很可能是自动释放的对象)将返回给A中的调用者。

在中nonatomic,没有此类保证。因此,nonatomic比“原子”要快得多。

什么“原子”并没有做的就是关于线程安全任何保证。如果线程A同时调用B和C的getter,而线程C使用不同的值调用setter,则线程A可能会获得返回的三个值中的任何一个-在调用任何setter之前的值之一,或者将其中一个值传递给setter同样,对象可能以B或C中的值结尾,无法分辨。

确保数据完整性(多线程编程的主要挑战之一)是通过其他方式实现的。

加上:

atomicity 当多个从属属性在起作用时,单个属性的“属性”也不能保证线程安全。

考虑:

 @property(atomic, copy) NSString *firstName;
 @property(atomic, copy) NSString *lastName;
 @property(readonly, atomic, copy) NSString *fullName;

在这种情况下,线程A可以通过先调用setFirstName:再调用来重命名对象setLastName:同时,线程B可能fullName在线程A的两次调用之间进行调用,并且将接收到新的名字以及旧的名字。

为了解决这个问题,您需要一个事务模型即某种其他类型的同步和/或排除,允许fullName在更新从属属性时排除访问

Apple的文档中对此进行了说明,但以下是一些实际情况的示例。

请注意,没有“ atomic”关键字,如果未指定“ nonatomic”,则该属性为atomic,但是显式指定“ atomic”将导致错误。

如果未指定“ nonatomic”,则该属性为atomic,但是如果需要,您仍可以在最新版本中显式指定“ atomic”。

//@property(nonatomic, retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    return userName;
}

- (void) setUserName:(UITextField *)userName_ {
    [userName_ retain];
    [userName release];
    userName = userName_;
}

现在,原子变体有点复杂:

//@property(retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    UITextField *retval = nil;
    @synchronized(self) {
        retval = [[userName retain] autorelease];
    }
    return retval;
}

- (void) setUserName:(UITextField *)userName_ {
    @synchronized(self) {
      [userName_ retain];
      [userName release];
      userName = userName_;
    }
}

基本上,原子版本必须采取锁定措施以确保线程安全,并且还在对象上增加引用计数(以及自动释放计数以使其平衡),以便确保调用者可以存在该对象,否则如果另一个线程正在设置该值,则是潜在的竞争条件,从而导致引用计数降至0。

实际上,根据属性是标量值还是对象以及保留,复制,只读,非原子等相互作用的方式,这些事物如何工作有许多不同的变体。通常,属性合成器只知道如何对所有组合执行“正确的事情”。

原子

  • 是默认行为
  • 在另一个进程访问变量之前,它将确保CPU完成当前进程
  • 速度不快,因为它可以确保流程完全完成

非原子

  • 不是默认行为
  • 更快(对于合成代码,即使用@property和@synthesize创建的变量)
  • 不是线程安全的
  • 当两个不同的进程同时访问同一变量时,可能会导致意外行为

理解差异的最好方法是使用以下示例。

假设有一个名为“ name”的原子字符串属性,并且如果您[self setName:@"A"]从线程A调用,[self setName:@"B"]从线程B调用以及[self name]从线程C调用,那么对不同线程的所有操作将按顺序执行,这意味着如果一个线程正在执行setter或吸气剂,然后其他线程将等待。

这使属性“名称”具有读/写安全性,但是如果另一个线程D[name release]同时调用,则此操作可能会导致崩溃,因为此处不涉及setter / getter调用。这意味着一个对象是读/写安全(ATOMIC)的,但不是线程安全的,因为另一个线程可以同时向该对象发送任何类型的消息。开发人员应确保此类对象的线程安全。

如果属性“名称”是非原子的,则上面示例中的所有线程-A,B,C和D将同时执行,从而产生任何不可预测的结果。在使用原子的情况下,A,B或C中的任何一个将首先执行,但D仍可以并行执行。

该问题的其他出色答案已经很好地定义了语法和语义。因为执行性能不够详细,所以我将添加答案。

这3个功能之间有什么区别?

我一直将atomic作为默认值感到非常好奇。在我们的抽象层次上,使用原子属性作为类来实现100%线程安全是一种极端的情况。对于真正正确的多线程程序,几乎可以肯定需要程序员的干预。同时,性能特征和执行方式尚未深入。这些年来,我编写了一些大量的多线程程序,但nonatomic由于原子对于任何目的都不明智,所以我一直在声明自己的属性在讨论这个问题的原子和非原子特性的详细信息期间,我进行了一些分析,并遇到了一些奇怪的结果。

执行

好。我要清除的第一件事是锁定实现是实现定义和抽象的。路易(Louis)@synchronized(self)在他的示例中使用了-我已经将其视为常见的混乱根源。实现并不实际使用@synchronized(self); 它使用对象级自旋锁Louis的插图非常适合使用我们都熟悉的结构进行高级插图,但重要的是要知道它不使用@synchronized(self)

另一个区别是原子属性将保留/释放对象在吸气剂中的循环。

性能

这是有趣的部分:在某些情况下,使用无争议(例如单线程)情况下的原子属性访问可以实现非常快的性能。在不太理想的情况下,使用原子访问的开销可能是的开销的20倍以上nonatomic对于三字节结构(2.2 GHz Core i7四核,x86_64),使用7个线程竞争情况要慢44倍三字节结构是一个非常慢的属性的示例。

有趣的是:三字节结构的用户定义访问器比合成原子访问器快52倍;或合成非原子访问器速度的84%。

在有争议的情况下,物体也可能超过50次。

由于实现中存在许多优化和变体,因此很难衡量在这些情况下的实际影响。您可能经常会听到类似“请信任它,除非您进行分析并发现问题”之类的内容。由于具有抽象级别,因此实际上很难衡量实际影响。从概要文件中收集实际成本可能非常耗时,并且由于抽象,因此非常不准确。同样,ARC vs MRC也可以发挥很大作用。

因此,让我们退后一步,而不是专注于属性访问的实现,我们将包括常见的可疑对象,例如objc_msgSend,并在一些无争议的情况下(以秒为单位的值)检查对NSString吸气剂的许多调用的一些真实的高级结果

  • MRC | 非原子| 手动实现的吸气剂:2
  • MRC | 非原子| 合成吸气剂:7
  • MRC | 原子| 合成吸气剂:47
  • ARC | 非原子| 合成吸气剂:38(注意:ARC在这里添加引用计数循环)
  • ARC | 原子| 合成吸气剂:47

您可能已经猜到,引用计数活动/循环是原子和ARC的重要贡献者。您还会在有争议的案例中看到更大的差异。

尽管我非常关注性能,但我还是说语义第一!同时,对于许多项目而言,性能并不是优先事项。但是,知道执行细节和所用技术的成本肯定不会受到损害。您应该根据需要,目的和能力使用正确的技术。希望这可以节省您几个小时的比较,并帮助您在设计程序时做出更明智的决定。

原子 =线程安全

非原子=无线程安全

线程安全性:

如果实例变量在从多个线程访问时正确运行,则它们是线程安全的,而不管运行时环境对那些线程的执行进行调度或交织,并且调用代码部分没有其他同步或其他协调。

在我们的上下文中:

如果线程更改了实例的值,则更改后的值可用于所有线程,并且一次只能有一个线程更改该值。

使用地点atomic

如果要在多线程环境中访问实例变量。

的含义atomic

速度并不快,nonatomic因为nonatomic它不需要从运行时进行任何看门狗工作。

使用地点nonatomic

如果实例变量不会被多个线程更改,则可以使用它。它提高了性能。

在阅读了很多文章,Stack Overflow的帖子并制作了演示应用程序以检查可变属性属性之后,我决定将所有属性信息放在一起:

  1. atomic //默认
  2. nonatomic
  3. strong = retain //默认
  4. weak = unsafe_unretained
  5. retain
  6. assign //默认
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite //默认

iOS中的变量属性属性或修饰符一文中,您可以找到上述所有属性,这肯定会对您有所帮助。

  1. atomic

    • atomic 表示只有一个线程访问该变量(静态类型)。
    • atomic 是线程安全的。
    • 但是性能慢
    • atomic 是默认行为
    • 在非垃圾回收环境中(例如,在使用保留/释放/自动释放时),原子访问器将使用锁来确保另一个线程不会干扰该值的正确设置/获取。
    • 它实际上不是关键字。

    例:

        @property (retain) NSString *name;
    
        @synthesize name;
    
  2. nonatomic

    • nonatomic 表示多线程访问变量(动态类型)。
    • nonatomic 是线程不安全的。
    • 但是性能很快
    • nonatomic不是默认行为。我们需要nonatomic在属性属性中添加关键字。
    • 当两个不同的进程(线程)同时访问同一变量时,可能会导致意外的行为。

    例:

        @property (nonatomic, retain) NSString *name;
    
        @synthesize name;
    

我发现原子和非原子性的一个很好的解释放在这里这是来自同一方面的一些相关文本:

“原子”意味着它不能被分解。用OS /编程术语来说,原子函数调用是不能中断的-整个函数必须执行,并且直到完成后,才通过OS的常规上下文切换将其交换出CPU。以防万一您不知道:由于CPU一次只能做一件事,因此OS会在很短的时间内将对所有正在运行的进程的CPU访问权轮流旋转,给人一种错觉多任务处理。CPU调度程序可以(并且确实)在执行的任何时刻中断进程,即使是在函数调用中间也是如此。因此,对于诸如更新共享计数器变量之类的操作(其中两个进程可以尝试同时更新变量),必须“以原子方式”执行它们,即,每个更新操作必须完整完成,然后才能将任何其他进程交换到该进程上。中央处理器。

因此,我猜想在这种情况下,atomic意味着属性读取器方法无法被中断-实际上,这意味着该方法读取的变量无法在途中更改其值,因为其他一些线程/调用/函数得到了交换到CPU上。

因为atomic变量不能被中断,所以确保它们在任何时候包含的值(线程锁定)都不会损坏,尽管确保此线程锁定会使访问它们的速度变慢。non-atomic另一方面,变量不提供此类保证,但确实提供了快速访问的优势。总结起来,non-atomic当您知道多个线程不会同时访问您的变量并加快速度时,请继续使用

原子的

原子保证将以原子方式执行对属性的访问。例如,它总是返回完全初始化的对象,一个线程上属性的任何获取/设置必须在另一个线程访问它之前完成。

如果您想象一下以下功能同时在两个线程上发生,那么您会明白为什么结果不理想。

-(void) setName:(NSString*)string
{
  if (name)
  {
    [name release]; 
    // what happens if the second thread jumps in now !?
    // name may be deleted, but our 'name' variable is still set!
    name = nil;
  }

  ...
}

优点:
在多线程的情况下,每次返回完全初始化的对象都是最佳选择。

缺点:
性能下降,执行速度稍慢

非原子:

与Atomic不同,它不能确保每次都完全初始化对象。

优点:
执行速度极快。

缺点:
在多线程的情况下,可能会产生垃圾值。

首先最简单的答案:后两个示例之间没有区别。默认情况下,属性访问器是原子的。

在非垃圾回收环境中(例如,在使用保留/释放/自动释放时),原子访问器将使用锁来确保另一个线程不会干扰该值的正确设置/获取。

有关创建更多信息以及创建多线程应用程序时的其他注意事项,请参阅Apple的Objective-C 2.0文档的“性能和线程”部分。

原子意味着只有一个线程访问该变量(静态类型)。原子是线程安全的,但速度很慢。

非原子意味着多个线程访问变量(动态类型)。非原子的线程不安全,但是速度很快。

Atomic是线程安全的,它运行缓慢,并且可以很好地确保(无法保证)无论在同一区域上尝试访问多少线程,都仅提供锁定值。当使用原子时,写在此函数内部的一段代码成为关键部分的一部分,一次只能执行一个线程。

它仅确保线程安全。它不能保证。我的意思是,您为汽车聘请了专业的驾驶员,但这仍然不能保证汽车不会发生事故。但是,可能性仍然是最小的。

原子-无法分解,因此可以预期。使用非原子-当另一个线程访问该内存区域时,它可以对其进行修改,因此结果是意外的。

代码对话:

原子使属性线程的getter和setter安全。例如,如果您写过:

self.myProperty = value;

是线程安全的。

[myArray addObject:@"Abc"] 

不是线程安全的。

没有这样的关键字“ atomic”

@property(atomic, retain) UITextField *userName;

我们可以像上面那样使用

@property(retain) UITextField *userName;

请参阅堆栈溢出问题,如果我使用@property(atomic,retain)NSString * myString,则会遇到问题

原子的(默认)

原子是默认设置:如果您不输入任何内容,则您的属性是原子的。保证原子属性,如果您尝试从中读取内容,则将取回有效值。它不能保证该值是多少,但是您将获得良好的数据,而不仅仅是垃圾内存。这允许您执行的操作是,如果您有多个线程或多个进程指向一个变量,则一个线程可以读取而另一个线程可以写入。如果它们同时命中,则保证读取器线程获得两个值之一:更改之前或更改之后。原子不会给您任何保证,您可能会获得其中哪些值。原子通常确实与线程安全混淆,这是不正确的。您需要以其他方式保证线程安全。

非原子的

另一方面,您可能会猜到,非原子意味着“不要做原子的事情”。您所失去的是保证您总是能得到一些回报。如果尝试在写入过程中进行读取,则可能会获取垃圾数据。但是,另一方面,您走得更快。因为原子属性必须做一些魔术才能保证您将获得一个值,所以它们要慢一些。如果这是您经常访问的属性,则可能需要降低为非原子属性,以确保不会造成速度损失。

在此处查看更多信息:https : //realm.io/news/tmi-objective-c-property-attributes/

默认情况下atomic,这意味着它无论您何时使用属性花费你的表现,但它是线程安全的。Objective-C的作用是设置一个锁,因此,只要执行了setter / getter,只有实际线程才能访问该变量。

具有ivar _internal的属性的MRC示例:

[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;

所以这最后两个是相同的:

@property(atomic, retain) UITextField *userName;

@property(retain) UITextField *userName; // defaults to atomic

另一方面,不会nonatomic向您的代码添加任何内容。因此,只有您自己编写安全性机制,它才是线程安全的。

@property(nonatomic, retain) UITextField *userName;

完全不必将关键字写为第一属性。

不要忘记,这并不意味着整个属性都是线程安全的。仅setter / getter的方法调用是。但是,如果您同时使用setter和具有两个不同线程的getter,则它也可能会损坏!

开始之前:您必须知道内存中的每个对象都需要从内存中重新分配,以使新的编写器能够发生。您不能像在纸上一样简单地在某些东西上写字。必须先擦除(取消分配)它,然后才能对其进行写入。如果目前擦除已完成(或已完成一半),尚未写入任何内容(或已写入一半),而您尝试读取它,则可能会很麻烦!原子和非原子可帮助您以不同方式解决此问题。

首先阅读问题,然后阅读Bbum的答案另外,请阅读我的总结。


atomic 将始终保证

  • 如果两个不同的人想同时读写,那么您的论文将不会燃烧!->即使在竞争条件下,您的应用程序也绝不会崩溃。
  • 如果一个人试图写,并且只写了8个字母中的4个,那么中间没有人可以阅读,只有当所有8个字母都写完之后才能进行阅读->不会发生read(get) “仍在写入的线程”,即如果要写入的字节数为8个字节,而仅写入4个字节,则直到此时为止,您都无法读取该线程。但是由于我说过它不会崩溃,所以它将从自动释放对象的值中读取
  • 如果之前已经擦除了以前写在纸上的东西,然后有人想要阅读,您仍然可以阅读。怎么样?您将从类似于Mac OS的垃圾箱中读取内容(由于垃圾箱仍未100%擦除...处于困境中)--->如果在ThreadB已经释放的情况下读取ThreadA进行读取,您将从ThreadB最终完全写入的值中获取一个值,或者从自动释放池中获取某些值。

保留计数是在Objective-C中管理内存的方式。创建对象时,其保留计数为1。向对象发送保留消息时,其保留计数将增加1。向对象发送释放消息时,其保留计数将减1。向对象发送自动释放消息,其保留计数在将来的某个阶段递减1。如果对象的保留计数减少到0,则将其释放。

  • 原子不能保证线程安全,尽管它对于实现线程安全很有用。线程安全与您编写代码的方式/从中读取/写入哪个线程队列有关。它仅保证不可崩溃的多线程。

什么?!多线程和线程安全性是否不同?

是。多线程意味着:多个线程可以同时读取一个共享的数据,并且我们不会崩溃,但这不能保证您不会从非自动释放的值中读取数据。借助线程安全性,可以确保您阅读的内容不会自动发布。我们默认情况下不使所有内容原子化的原因是,这会降低性能,并且在大多数情况下实际上并不需要线程安全性。我们的代码的某些部分需要它,而对于那部分,我们需要使用锁,互斥或同步以线程安全的方式编写代码。


nonatomic

  • 由于没有像Mac OS Trash Bin这样的东西,所以没有人关心您是否总是得到一个值(<-这可能导致崩溃),也没有人关心是否有人尝试在写作过程中进行阅读(尽管在内存中进行中途写作与在纸上进行中途写作有很大的不同,在内存中它可能会给您一个从前的疯狂愚蠢的价值,而在纸上您只会看到一半的写作内容)->不保证不会崩溃,因为它不使用自动释放机制。
  • 不保证阅读完整的书面价值!
  • 比原子快

总体而言,它们在两个方面有所不同:

  • 是否因没有自动释放池而崩溃。

  • 允许在“尚未完成的写入或空值”中间进行读取,或者不允许并且仅在值被完全写入时才允许读取

如果您在多线程代码中使用属性,那么您将能够看到非原子属性和原子属性之间的区别。非原子比原子更快,并且原子是线程安全的,而不是非原子的。

Vijayendra Tripathi已经给出了多线程环境的示例。

  • -Atomic表示仅一个线程访问该变量(静态类型)。
  • -原子是线程安全的。
  • -但是性能很慢

如何申报:

由于默认是原子的,

@property (retain) NSString *name;

实施文件中的AND

self.name = @"sourov";

假设与三个属性有关的任务是

 @property (retain) NSString *name;
 @property (retain) NSString *A;
 @property (retain) NSString *B;
 self.name = @"sourov";

所有属性并行工作(例如异步工作)。

如果您从线程A调用“名称”

同时拨打

[self setName:@"Datta"]

从线程B开始

现在,如果* name属性是非原子的,

  • 它将为A返回值“ Datta”
  • 它将为B返回值“ Datta”

这就是为什么将非原子的称为线程不安全的原因,但是由于并行执行,它的性能很快

现在,如果* name属性是atomic

  • 它将确保A的值“ Sourov”
  • 然后它将为B返回值“ Datta”

这就是为什么atomic称为线程安全,也
就是为什么它称为读写安全的原因

这种情况操作将串行执行。
而且性能慢

-非原子意味着多线程访问变量(动态类型)。

-非原子是线程不安全的。

-但性能很快

-nonatomic不是默认行为,我们需要在property属性中添加nonatomic关键字。

对于In Swift,确认ObjC意义上的Swift属性是非原子的。原因之一是您要考虑按属性原子性是否足以满足您的需求。

参考:https : //forums.developer.apple.com/thread/25642

有关更多信息,请访问网站
http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html

原子原子性(默认)

原子是默认设置:如果您不输入任何内容,则您的属性是原子的。保证原子属性,如果您尝试从中读取内容,则将取回有效值。它不能保证该值是多少,但是您将获得良好的数据,而不仅仅是垃圾内存。这允许您执行的操作是,如果您有多个线程或多个进程指向一个变量,则一个线程可以读取而另一个线程可以写入。如果它们同时命中,则保证读取器线程获得两个值之一:更改之前或更改之后。原子不会给您任何保证,您可能会获得其中哪些值。原子通常确实与线程安全混淆,这是不正确的。您需要以其他方式保证线程安全。

非原子的

另一方面,您可能会猜到,非原子意味着“不要做原子的事情”。您所失去的是保证您总是能得到一些回报。如果尝试在写入过程中进行读取,则可能会获取垃圾数据。但是,另一方面,您走得更快。因为原子属性必须做一些魔术才能保证您将获得一个值,所以它们要慢一些。如果这是您经常访问的属性,则可能需要降低为非原子属性,以确保不会造成速度损失。访问

https://academy.realm.io/posts/tmi-objective-c-property-attributes/提供

原子性属性(原子的和非原子的)没有反映在相应的Swift属性声明中,但是从Swift访问导入的属性时,Objective-C实现的原子性保证仍然有效。

因此,如果您在Objective-C中定义一个原子属性,当Swift使用它时它将保持原子性。


https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c提供

原子属性可确保保留完全初始化的值,而不管有多少线程正在对其执行getter和setter方法。

nonatomic属性指定合成的访问器仅直接设置或返回一个值,而不保证如果从不同的线程同时访问相同的值会发生什么情况。

原子意味着一次只能有一个线程访问该变量(静态类型)。原子是线程安全的,但速度很慢。

非原子意味着多个线程可以同时访问变量(动态类型)。非原子的线程不安全,但是速度很快。

如果您使用原子,则意味着该线程将是安全的并且是只读的。如果您使用的是非原子操作,则意味着多个线程访问该变量并且是线程不安全的,但是它执行速度很快,完成了读取和写入操作;这是动态类型。

事实是,他们使用自旋锁来实现原子属性。代码如下:

 static inline void reallySetProperty(id self, SEL _cmd, id newValue, 
      ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy) 
    {
        id oldValue;
        id *slot = (id*) ((char*)self + offset);

        if (copy) {
            newValue = [newValue copyWithZone:NULL];
        } else if (mutableCopy) {
            newValue = [newValue mutableCopyWithZone:NULL];
        } else {
            if (*slot == newValue) return;
            newValue = objc_retain(newValue);
        }

        if (!atomic) {
            oldValue = *slot;
            *slot = newValue;
        } else {
            spin_lock_t *slotlock = &PropertyLocks[GOODHASH(slot)];
            _spin_lock(slotlock);
            oldValue = *slot;
            *slot = newValue;        
            _spin_unlock(slotlock);
        }

        objc_release(oldValue);
    }

为了简化整个混乱,让我们了解互斥锁。

互斥锁,按名称,锁定对象的可变性。因此,如果一个类访问该对象,则其他任何类都不能访问同一对象。

在iOS中,@sychronise还提供了互斥锁。现在它以FIFO模式提供服务,并确保流程不受共享同一实例的两个类的影响。但是,如果任务在主线程上,请避免使用原子属性访问对象,因为它可能会占用您的UI并降低性能。

原子:通过使用NSLOCK锁定线程来确保线程安全。

非原子的:由于没有线程锁定机制,因此不能确保线程安全。

原子属性:-当一个分配了原子属性的变量时,它仅具有一个线程访问权限,并且将是线程安全的,并且在性能方面会很好,它将具有默认行为。

非原子属性:-当分配了原子属性的变量表示其具有多线程访问权限,并且不是线程安全的,并且性能下降时,将具有默认行为,并且两个不同的线程希望同时访问变量它会产生意想不到的结果。

本文地址:http://ios.askforanswer.com/yuanzishuxinghefeiyuanzishuxingyoushenmequbie.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!