iOS两个线程间嵌套发送同步消息

简介:  先上代码,主要逻辑可看注释。最好是直接下载demo再往下看了。demo下载地址:http://download.csdn.net/detail/hursing/5159144@implementation ViewController #d...

 先上代码,主要逻辑可看注释。最好是直接下载demo再往下看了。demo下载地址:http://download.csdn.net/detail/hursing/5159144

@implementation ViewController 
 
#define kLevelsOfNesting 5 
NSString *const kParameter = @"Parameter"; 
NSString *const kRunLoop = @"RunLoop"; 
 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // 在界面上增加一个button,点击后才触发发送消息的流程 
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    [button setTitle:@"click me" forState:UIControlStateNormal]; 
    [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; 
    button.frame = CGRectMake(50, 50, 100, 30); 
    [self.view addSubview:button]; 
    [NSThread mainThread].name = @"Main Thread"; 
    // 创建一个worker线程 
    m_thread = [[NSThread alloc] initWithTarget:self selector:@selector(secondaryThreadMain:) object:nil]; 
    [m_thread start]; 
} 
 
- (void)sendSynchronousMessageToTheOtherThread:(NSMutableDictionary*)info 
{ 
    // 不能存NSRunLoop进去,它非线程安全 
    NSValue *runLoop = [NSValue valueWithPointer:CFRunLoopGetCurrent()]; 
    [info setObject:runLoop forKey:kRunLoop]; 
    NSThread *targetThread = [NSThread isMainThread] ? m_thread : [NSThread mainThread]; 
    [self performSelector:@selector(executeOperation:) onThread:targetThread withObject:info waitUntilDone:NO]; 
    CFRunLoopRun();  // 开始一个嵌套的RunLoop 
} 
 
- (void)executeOperation:(NSMutableDictionary*)info 
{ 
    NSNumber* number = [info objectForKey:kParameter]; 
    CFRunLoopRef runLoop = [(NSValue*)[info objectForKey:kRunLoop] pointerValue]; 
    int count = [number intValue]; 
    NSLog(@"count is reduced to %d on %@", --count, [NSThread currentThread].name); 
    if (count) 
    { 
        number = [NSNumber numberWithInt:count]; 
        [info setObject:number forKey:kParameter]; 
        [self sendSynchronousMessageToTheOtherThread:info]; 
    } 
    CFRunLoopStop(runLoop);  // 停止掉RunLoop栈栈顶的RunLoop 
} 
 
- (void)buttonClicked:(UIButton*)button 
{ 
    static bool mainThreadFirst = false; 
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kLevelsOfNesting], kParameter, nil]; 
    mainThreadFirst = !mainThreadFirst; 
    if (mainThreadFirst) 
    { 
        [self sendSynchronousMessageToTheOtherThread:dictionary]; 
        NSLog(@"-------Because of nesting synchonization, this log is printed at the end.-------"); 
    } 
    else 
        [self performSelector:@selector(sendSynchronousMessageToTheOtherThread:) onThread:m_thread withObject:dictionary waitUntilDone:NO]; 
     
} 
 
- (void)secondaryThreadMain:(id)para 
{ 
    @autoreleasepool { 
        [NSThread currentThread].name = @"Secondary Thread"; 
        NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; 
        NSThread *thread = [NSThread currentThread]; 
        NSPort *port = [NSMachPort port];       // 阻塞RunLoop 
        [currentRunLoop addPort:port forMode:NSDefaultRunLoopMode]; 
        NSDate *distantFuture = [NSDate distantFuture]; 
         
        while (!thread.isCancelled) 
        { 
            NSAutoreleasePool *pool = [NSAutoreleasePool new]; 
            NSLog(@"RunLoop runs once");     
            [currentRunLoop runUntilDate:distantFuture]; // 这里会阻塞,直到有事件触发 
            [pool drain]; 
        } 
         
        [currentRunLoop removePort:port forMode:NSDefaultRunLoopMode]; 
    } 
} 
 
- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 
 
@end 

运行demo工程,点击一下button,看看log输出就懂有什么用了。或者在第61行

CFRunLoopStop(runLoop);  // 停止掉RunLoop栈栈顶的RunLoop 

加个断点,看看堆栈,会在两个线程都看到嵌套的RunLoop.堆栈截图如下:



实用例子
子线程想创建一个UIView,发同步消息到主线程创建(UIKit对象都得主线程操作),主线程创建过程中又需要去子线程执行一段代码做些判断,这又需要主线程发同步消息回子线程;如果使用锁技术,这就是死锁。
RunLoop的东西很复杂,认真看文档最实际了。也可以重点看CFRunLoopRun和CFRunLoopStop两个函数。

附:
关于NSRunLoop和CFRunLoop需要注意的地方:
Warning:  The NSRunLoop class is generally not considered to be thread-safe and its methods should only be called within the context of the current thread. You should never try to call the methods of an NSRunLoop object running in a different thread, as doing so might cause unexpected results.
Although they are not toll-free bridged types, you can get a CFRunLoopRef opaque type from an NSRunLoop object when needed. The NSRunLoop class defines a getCFRunLoop method that returns a CFRunLoopRef type that you can pass to Core Foundation routines. Because both objects refer to the same run loop, you can intermix calls to the NSRunLoop object and CFRunLoopRef opaque type as needed.
Thread safety varies depending on which API you are using to manipulate your run loop. The functions in Core Foundation are generally thread-safe and can be called from any thread. If you are performing operations that alter the configuration of the run loop, however, it is still good practice to do so from the thread that owns the run loop whenever possible.

The Cocoa NSRunLoop class is not as inherently thread safe as its Core Foundation counterpart. If you are using the NSRunLoop class to modify your run loop, you should do so only from the same thread that owns that run loop. Adding an input source or timer to a run loop belonging to a different thread could cause your code to crash or behave in an unexpected way.
目录
相关文章
|
30天前
|
Java 云计算
Java多线程编程中的同步与互斥机制探析
在当今软件开发领域,多线程编程是一项至关重要的技能。本文将深入探讨Java中的同步与互斥机制,分析其在多线程环境下的应用及实现原理,帮助读者更好地理解并运用这一关键技术。
22 4
|
1月前
|
Python
在Python中,如何保证多个线程之间的同步?
在Python中,如何保证多个线程之间的同步?
22 4
|
1月前
|
Python
如何在Python中实现线程之间的同步和通信?
【2月更文挑战第17天】【2月更文挑战第51篇】如何在Python中实现线程之间的同步和通信?
|
1月前
|
算法 调度 索引
什么是多任务和线程?用线程写的一个udp同步聊天器
什么是多任务和线程?用线程写的一个udp同步聊天器
30 0
|
3月前
|
存储 设计模式 安全
Java 编程问题:十、并发-线程池、可调用对象和同步器2
Java 编程问题:十、并发-线程池、可调用对象和同步器
|
3月前
|
缓存 安全 Java
Java 编程问题:十、并发-线程池、可调用对象和同步器1
Java 编程问题:十、并发-线程池、可调用对象和同步器
|
25天前
|
存储 编解码 算法
【ffmpeg音视频同步】解决ffmpeg音视频中多线程之间的数据同步问题
【ffmpeg音视频同步】解决ffmpeg音视频中多线程之间的数据同步问题
38 2
|
30天前
|
安全 C++ 开发者
【C++多线程同步】C++多线程同步和互斥的关键:std::mutex和相关类的全面使用教程与深度解析
【C++多线程同步】C++多线程同步和互斥的关键:std::mutex和相关类的全面使用教程与深度解析
18 0
|
1月前
|
安全 Java 程序员
Java中的并发编程:掌握同步机制与线程安全
【2月更文挑战第12天】 在现代软件开发领域,多线程和并发编程已成为提高应用性能和资源利用率的关键技术。Java语言提供了丰富的并发编程工具和框架,使得开发高效、可靠的并发应用成为可能。本文将深入探讨Java中的并发编程,着重介绍同步机制、线程安全概念及其在实际开发中的应用。通过对这些知识点的深入分析和案例演示,旨在帮助读者建立起对Java并发编程的全面理解,从而更好地设计和实现线程安全的高并发系统。

热门文章

最新文章