• objective-c中是如何实现线程同步的?


    多线程在各种编程语言中都是难点,很多语言中实现起来很麻烦,objective-c虽然源于c,但其多线程编程却相当简单,可以与java相媲美。这篇文章主要从线程创建与启动、线程的同步与锁、线程的交互、线程池等等四个方面简单的讲解一下iphone中的多线程编程。  
    一、线程创建与启动  
    线程创建主要有二种方式:  
    当然,还有一种比较特殊,就是使用所谓的convenient method,这个方法可以直接生成一个线程并启动它,而且无需为线程的清理负责。这个方法的接口是:   
    + (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument  
    前两种方法创建后,需要手机启动,启动的方法是:  
    - (void)start;  
    二、线程的同步与锁  
    要说明线程的同步与锁,最好的例子可能就是多个窗口同时售票的售票系统了。我们知道在java中,使用synchronized来同步,而iphone虽然没有提供类似java下的synchronized关键字,但提供了NSCondition对象接口。查看NSCondition的接口说明可以看出,NSCondition是iphone下的锁对象,所以我们可以使用NSCondition实现iphone中的线程安全。这是来源于网上的一个例子:  
    SellTicketsAppDelegate.h 文件  
    //  SellTicketsAppDelegate.h  
    import <UIKit/UIKit.h>  
       
    @interface SellTicketsAppDelegate : NSObject <UIApplicationDelegate> {  
         int tickets;  
         int count;  
         NSThread* ticketsThreadone;  
         NSThread* ticketsThreadtwo;  
         NSCondition* ticketsCondition;  
         UIWindow *window;  
     }  
    @property (nonatomic, retain) IBOutlet UIWindow *window;  
    @end  
    SellTicketsAppDelegate.m 文件  
    //  SellTicketsAppDelegate.m  
    import "SellTicketsAppDelegate.h" 
       
    @implementation SellTicketsAppDelegate  
    @synthesize window;  
       
    - (void)applicationDidFinishLaunching:(UIApplication *)application {  
         tickets = 100;  
         count = 0;  
         // 锁对象  
         ticketCondition = [[NSCondition alloc] init];  
         ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  
         [ticketsThreadone setName:@"Thread-1"];  
         [ticketsThreadone start];    
       
       
         ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  
         [ticketsThreadtwo setName:@"Thread-2"];  
         [ticketsThreadtwo start];  
         //[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];  
          // Override point for customization after application launch  
         [window makeKeyAndVisible];   
       
     }  
       
    - (void)run{  
         while (TRUE) {  
            // 上锁  
            [ticketsCondition lock];  
             if(tickets > 0){  
                 [NSThread sleepForTimeInterval:0.5];  
                 count = 100 - tickets;  
                 NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);  
                 tickets--;  
             }else{  
                 break;  
            }  
             [ticketsCondition unlock];  
         }  
     }  
       
    - (void)dealloc {  
        [ticketsThreadone release];  
         [ticketsThreadtwo release];  
         [ticketsCondition release];   
         [window release];  
         [super dealloc];  
    }  
    @end  
    三、线程的交互  
    线程在运行过程中,可能需要与其它线程进行通信,如在主线程中修改界面等等,可以使用如下接口:  
    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait  
    由于在本过程中,可能需要释放一些资源,则需要使用NSAutoreleasePool来进行管理,如:  
    - (void)startTheBackgroundJob {  
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
        // to do something in your thread job  
        ...  
        [self performSelectorOnMainThread:@selector(makeMyProgressBarMoving) withObject:nil waitUntilDone:NO];  
        [pool release];  
    }  
    如果你什么都不考虑,在线程函数内调用 autorelease 、那么会出现下面的错误:  
    .NSAutoReleaseNoPool(): Object 0x********* of class NSConreteData autoreleased with no pool in place ….  
    四、关于线程池,大家可以查看NSOperation的相关资料。  

  • 相关阅读:
    SqlDependency和SqlCacheDependency的若干说明
    sublime 3 随笔
    [有得]解决redmine写操作很慢的问题
    Java双重循环
    使用 Docker 打包 Rust Web 服务
    Centos8.3、hadoop-2.6.4 简单的日志分析实验
    广域网数据交换的三种方式
    计算机的起源与发展
    推荐两款生成数据库表结构说明文档工具
    Centos8.3、docker部署springboot项目实战记录
  • 原文地址:https://www.cnblogs.com/ccguo/p/3353628.html
Copyright © 2020-2023  润新知