簡體   English   中英

原始類型的Objective-c屬性

[英]Objective-c properties for primitive types

在Objective-C中將原始類型的屬性指定nonatomic是否有意義?

我想知道這兩個屬性之間的區別:

@property (nonatomic) BOOL myBool;
@property BOOL myBool;

答案在技術上是肯定的它們是不同的,但實際上它們不是,除非你編寫自己的訪問器。

讓我解釋。 對於對象指針屬性,比如@property NSObject *foo ,如果使用合成訪問器,則生成的代碼中存在明顯且重要的差異。 這在Apple文檔中有描述,它指出如果屬性是原子的,則合成訪問器將鎖定對象(如果未指定非原子,則默認情況下它將變為原子)

所以對於對象屬性在一個非常粗略的概述:非原子更快但不是線程安全,原子(你不能指定它,但它的默認值)是線程安全但可能更慢。

(注意:如果你習慣使用Java,你可以考慮使用nonatomic ,就像指定synchronized ,而不是指定nonatomic就像指定synchronized 。換句話說,atomic = synchronized)

但是BOOL是一個原語 - 實際上是一個C簽名的char,所以訪問應該是原子的,而不是像Jano的回答中提到的那樣鎖定對象。 因此,當您合成訪問器時,有兩種可能性:1:編譯器是智能的並且看到該屬性是原始的並且避免鎖定它,2:編譯器總是鎖定對象的原子屬性

據我所知,這在任何地方都沒有記錄,所以我嘗試使用XCode中的Generate-> Assembly選項並進行比較。 答案並不是完全確定的,但足以說我幾乎可以肯定答案是#1,編譯器很聰明。 我這樣說,因為為原子對象屬性生成的匯編代碼與非原子對象屬性有很大不同(更多):這是鎖定對象的所有代碼。 另一方面,對於BOOL屬性,只有一行不同 - 單個“mov”看起來不像它可能會有所不同。 我還是想知道。 有趣的是,另一個區別是BOOL的原子版本有一些額外的注釋輪廓用於調試 - 所以編譯器顯然對它的處理方式不同。

盡管如此,我認為它們的相似之處在於實際目的。

但是它們在技術上仍然存在差異,如果你看不到實現,那么你正在閱讀的其他一些庫(你自己沒有自己編寫代碼)可能會有實質性的不同,這就是原因: 原子屬性有契約 合同說:“如果您在多個線程上訪問我的值,我保證每個設置或獲取操作將在任何其他線程開始之前完成”。

但是,你說,BOOL仍然是自然原子的,所以這個契約不是隱含的嗎?

不。BOOL 變量自然是原子的,但我們談的是屬性 屬性可能無法合成,甚至可能沒有單個變量來備份它。 這實際上很常見。 考慮:

@property (getter=isEmptyThingo) BOOL emptyThingo;

...
- (BOOL)isEmptyThingo
{
    Thingo *thingo = [self deriveTheThingo];
    if ([thingo length] == 0) {
        return YES;
    }
    return NO;
}

誰知道deriveTheThingo什么? 好吧,這有點做作,但關鍵是isEmptyThingo - 我們的getter看起來不是很原子,是嗎? 如果一個線程正在派生thingo而另一個線程調用以查找它是否為空,會發生什么。

長話短說:財產不是原子的。 所以我們應該這樣宣布。

因此m原始答案合格:如果你自己編寫這個屬性並使用@synthesize,那么它們可能是相同的,但你通常不應該對它們進行同樣的處理。

根據經驗,如果您不需要多線程支持 - 如果您在UIViewControllers等UI代碼中工作,通常不需要多線程支持,那么只需將其聲明為非原子的。

在x位架構(例如:32位,64位等)中,任何x或更小位的值將始終以原子方式讀取或寫入。 這是任何理智的硬件實現的屬性。

默認的原子屬性意味着始終設置或獲取屬性值,而忽略其他線程正在執行的操作。 這只是超出體系結構位數的屬性的一個問題。 編譯器在任何其他類型上完全忽略Nonatomic。

例:

@property struct { int d; } flag;
@property (atomic) struct { float x; float y; } point;
@property (atomic,copy) NSString *s;
  • struct { int d; } struct { int d; }已經是原子,因此accesors不需要互斥。

  • struct { float x, float y}不是原子的,則它可能處於不一致狀態。 示例:設置{1,2}{3,4}兩個線程可能與寫入重疊,結構可能最終得到每個集合中的值: {1,4}

  • 指針存儲在單個內存位置,但它們需要多個語句來進行內存管理。

原子屬性有助於線程安全,避免導致不一致的值或內存管理失敗的競爭條件。 僅此一項並不能保證線程安全,因為它不會處理其他問題,如死鎖,飢餓,可見性等。

是。 nonatomic不是內存管理關鍵字,它與線程安全有關。 此外,默認情況下屬性是原子的(沒有明確聲明它們是非原子的),因此您列出的兩個聲明之間存在差異。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM