CFStringTransform线程安全且可重入吗?

时间:2012-10-05 16:57:49

标签: ios multithreading nsmutablestring

在全局后台队列中同时调用多个semaphore_wait_trap实例时,我看到我的应用程序陷入死锁状态(主线程在CFStringTransform中等待,请参阅下面的调用堆栈)几次如下:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    CFStringTransform(…);
});

调用堆栈如下所示:

Thread 1, Queue : com.apple.main-thread
#0  0x310bff04 in semaphore_wait_trap ()
#1  0x341c1fae in _dispatch_semaphore_wait_slow ()
#2  0x32bc5c32 in SBSProcessAssertionCreateForPID ()
#3  0x3685bca4 in -[UIApplication beginBackgroundTaskWithExpirationHandler:] ()
#4  0x0011a1c2 in -[XXX downloadPicture:]
…
#10 0x32f86a6e in __NSFireDelayedPerform ()
#11 0x354a15de in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#12 0x354a1290 in __CFRunLoopDoTimer ()
#13 0x3549ff00 in __CFRunLoopRun ()
#14 0x35412ebc in CFRunLoopRunSpecific ()
#15 0x35412d48 in CFRunLoopRunInMode ()
#16 0x3594f2ea in GSEventRunModal ()
#17 0x367f1300 in UIApplicationMain ()
#18 0x000c3eb8 in main


Thread 3, Queue : com.apple.libdispatch-manager
#0  0x310c0648 in kevent64 ()
#1  0x341c3978 in _dispatch_mgr_invoke ()
#2  0x341c3658 in _dispatch_mgr_thread$VARIANT$mp ()


Thread 5 WebThread, Queue : (null)
#0  0x310bfeb4 in mach_msg_trap ()
#1  0x310c004c in mach_msg ()
#2  0x354a1044 in __CFRunLoopServiceMachPort ()
#3  0x3549fda2 in __CFRunLoopRun ()
#4  0x35412ebc in CFRunLoopRunSpecific ()
#5  0x35412d48 in CFRunLoopRunInMode ()
#6  0x349b6a74 in RunWebThread(void*) ()
#7  0x3925f310 in _pthread_start ()
#8  0x3925f1d8 in thread_start ()


Thread 11 com.apple.NSURLConnectionLoader, Queue : (null)
#0  0x310bfeb4 in mach_msg_trap ()
#1  0x310c004c in mach_msg ()
#2  0x354a1044 in __CFRunLoopServiceMachPort ()
#3  0x3549fda2 in __CFRunLoopRun ()
#4  0x35412ebc in CFRunLoopRunSpecific ()
#5  0x35412d48 in CFRunLoopRunInMode ()
#6  0x32f0bbcc in +[NSURLConnection(Loader) _resourceLoadLoop:] ()
#7  0x32f8f67c in __NSThread__main__ ()
#8  0x3925f310 in _pthread_start ()
#9  0x3925f1d8 in thread_start ()


Thread 14 com.apple.CFSocket.private, Queue : (null)
#0  0x310d0594 in select$DARWIN_EXTSN ()
#1  0x354a51f6 in __CFSocketManager ()
#2  0x3925f310 in _pthread_start ()
#3  0x3925f1d8 in thread_start ()

和31个线程调用CFStringTransform

Thread 12, Queue : com.apple.root.default-priority
#0  0x310d00fc in __psynch_mutexwait ()
#1  0x3924f128 in pthread_mutex_lock ()
#2  0x31448548 in umtx_lock ()
#3  0x3144a090 in icu::UnicodeString::doReplace(int, int, unsigned short const*, int, int) ()
#4  0x314a5b3a in icu::UnicodeString::append(int) ()
#5  0x314a1510 in icu::UnicodeSet::_appendToPat(icu::UnicodeString&, int, signed char) ()
#6  0x314a168c in icu::UnicodeSet::_generatePattern(icu::UnicodeString&, signed char) const ()
#7  0x314a2e4e in icu::UnicodeSet::applyPattern(icu::RuleCharacterIterator&, icu::SymbolTable const*, icu::UnicodeString&, unsigned int, icu::UnicodeSet& (icu::UnicodeSet::*)(int), UErrorCode&) ()
#8  0x314a1e7c in icu::UnicodeSet::applyPattern(icu::UnicodeString const&, icu::ParsePosition&, unsigned int, icu::SymbolTable const*, UErrorCode&) ()
#9  0x314a1e06 in icu::UnicodeSet::UnicodeSet(icu::UnicodeString const&, icu::ParsePosition&, unsigned int, icu::SymbolTable const*, UErrorCode&) ()
#10 0x314a1d8e in icu::UnicodeSet::UnicodeSet(icu::UnicodeString const&, icu::ParsePosition&, unsigned int, icu::SymbolTable const*, UErrorCode&) ()
#11 0x314fe56c in ___lldb_unnamed_function2011$$libicucore.A.dylib ()
#12 0x314fda50 in ___lldb_unnamed_function2010$$libicucore.A.dylib ()
#13 0x314fd954 in ___lldb_unnamed_function2009$$libicucore.A.dylib ()
#14 0x314ff540 in ___lldb_unnamed_function2031$$libicucore.A.dylib ()
#15 0x314feed6 in ___lldb_unnamed_function2025$$libicucore.A.dylib ()
#16 0x314feb0c in ___lldb_unnamed_function2024$$libicucore.A.dylib ()
#17 0x31521468 in ___lldb_unnamed_function2248$$libicucore.A.dylib ()
#18 0x3152015a in icu::Transliterator::createBasicInstance(icu::UnicodeString const&, icu::UnicodeString const*) ()
#19 0x31522cd6 in ___lldb_unnamed_function2296$$libicucore.A.dylib ()
#20 0x31523c32 in ___lldb_unnamed_function2305$$libicucore.A.dylib ()
#21 0x3152003a in icu::Transliterator::createInstance(icu::UnicodeString const&, UTransDirection, UParseError&, UErrorCode&) ()
#22 0x315200d6 in icu::Transliterator::createInstance(icu::UnicodeString const&, UTransDirection, UErrorCode&) ()
#23 0x314bfc1c in ___lldb_unnamed_function1051$$libicucore.A.dylib ()
#24 0x314bfb0e in ___lldb_unnamed_function1050$$libicucore.A.dylib ()
#25 0x3151fada in icu::Transliterator::filteredTransliterate(icu::Replaceable&, UTransPosition&, signed char, signed char) const ()
#26 0x3151f724 in icu::Transliterator::transliterate(icu::Replaceable&, int, int) const ()
#27 0x3154a8da in utrans_trans ()
#28 0x354b3928 in CFStringTransform ()
#30 0x002716c8 in __18-[Foo bar]_block_invoke_0
#31 0x341bd11e in _dispatch_call_block_and_release ()
#32 0x341c1960 in _dispatch_root_queue_drain ()
#33 0x341c1ac0 in _dispatch_worker_thread2 ()
#34 0x39254a10 in _pthread_wqthread ()
#35 0x392548a4 in start_wqthread ()

似乎问题发生在字符串修改调用doReplace中。但它似乎doReplace是线程安全的,因为它使用互斥锁,因此多个线程可以同时修改相同的可变字符串。事实上,就我而言,多个线程都没有修改可变字符串 - 每个CFStringTransform都被调用一个唯一的字符串。所以基本上,我不知道为什么会卡住。

1 个答案:

答案 0 :(得分:0)

有趣。

ICU字符串转换位于名为libicucore的库中。 Mac OS 10.8版本的源代码is available here

doReplace功能在icuSources/common/unistr.cpp中实施,但不会直接调用umtx_lock。 iOS可能会使用该库的另一个版本,或者调用可能只是在内联函数(或预处理器魔术)中。所以我无法确定锁是全局共享锁还是每个字符串都有一个。

无论如何,我在Mac OS上做了一些测试(24k字符串,10000个调度块),但没有成功重现死锁。

您确定您的代码仍未运行吗?所有线程都在同一个堆栈框架中吗?