2012-01-17 126 views
0

我有一個很少發生的錯誤,其中一個NSMutableDictionary實例中的鍵最終指向錯誤的對象(同一字典中的另一個對象)。NSMutableDictionary不是線程安全的:那麼?

「關鍵混淆」是否是競爭條件的結果?

下面的代碼(我已經把新的線程安全性,因爲):

- (NSNumber*) makeHashFromResizedImage:(UIImage*)original newSize:(CGSize)newSize { 
    int retVal = original.hash + newSize.width * 2 + newSize.height * 4; 
    return [NSNumber numberWithInteger:retVal]; 
} 

- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize { 
    NSNumber *key = [self makeHashFromResizedImage:image newSize:newSize]; 

    if ([self.resizedImages objectForKey:key]) { 
     return [self.resizedImages objectForKey:key]; 
    } 

    UIImage *newImage = {{image-resizing-code-here}}; 

    [self.resizedImages setObject:newImage forKey:key]; 

    return newImage; 
} 

注意{{image-resizing-code-here}}是爲簡潔,刪除。我開始懷疑我的makeHashFromResizedImage,因爲它可能無法按預期工作。去單位現在測試它。

+0

請顯示您的代碼。 (是的,[NSDictionary是不是線程安全的](http://stackoverflow.com/questions/1986736/nsmutabledictionary-thread-safety)。) – kennytm 2012-01-17 18:04:51

+0

@KennyTM我想說我的代碼是不相關的,但肯定這是相關的,我可能看錯了。例如,我的'makeHashFromResizedImage'看起來也可能有float-and-int問題。代碼已發佈。 – 2012-01-17 19:05:20

+0

如果你擔心使NSDictionary線程安全,看看這個問題[這裏](http://stackoverflow.com/questions/8763028/how-can-i-make-every-message-an-object-receives-thread - 安全) – 2012-01-17 19:14:21

回答

2

此:

if ([self.resizedImages objectForKey:key]) { 
    return [self.resizedImages objectForKey:key]; 
} 

如果另一個線程調用setObject:forKey:key 2號線的結果將是從第一行不同。爲什麼不把它存儲在一個變量中?至少你檢查的東西和你返回的東西是一樣的。

UIImage* image = [[[[self.resizedImages objectForKey:key] retain] autorelease]; 
if (image) { 
    return image; 
} 

(該retain + autorelease只是保留image不會當這個線程運行-dealloc -ed。)

如果你必須確保對應於imagekey不會在函數返回之前被覆蓋,您需要使用鎖,正如其他人所回答的。


編輯:也許你應該使用的UIImage的的NSMutableSet代替。特別是,不要使用散列值作爲關鍵字!當兩個對象不相同時,散列值不需要不同。如果可以多次添加相同的UIImage,則創建一個包含CGSize和UIImage屬性的新類X,並使用X的NSMutableSet。

+0

謝謝!首先,這是所有ARC下,只是爲了簡化。其次,我不介意別人是否爲我的鑰匙提供對象,因爲它應該指向相同的圖像,並以相同的方式重新調整大小。現在我開始懷疑我的哈希函數,這看起來很錯誤。 – 2012-01-17 19:20:13

+0

@Yar:如果它在ARC中,那麼就放棄'retain'和'autorelease',因爲__strong變量應該爲你做。 – kennytm 2012-01-17 19:25:43

+0

@Yar:檢查更新。 – kennytm 2012-01-17 19:31:51

-1

NSMutableDictionary不是線程安全的。這取決於你提供鎖定。

+0

您是否回答了問題的標題或問題? – 2012-01-17 19:06:38

2

正如羅布所言:你需要自己提供排除。

是的,「關鍵混淆」可能是一個競爭條件的結果,但它是極不可能的。更有可能你會以間歇性崩潰結束。但是,當然,由於腐敗和未定義的行爲,錯位的價值可能會發生。

+0

謝謝。我可能沒有看到正確的問題。我用一些代碼更新了這個問題。 – 2012-01-17 19:05:51