线程的同步执行@synchronized

Objective-C在应用程序中支持多任务。这意味着可能有两个线程同时视图徐改同一个对象。有一个办法可以解决这个情况。为了防止多个线程同时执行同一个代码块,OC提供了@synchronized()指令。
使用@synchronized()指令可以锁住在线程中执行的某一个代码块。存在被保护(即被锁住)的代码块的其他线程,将被阻塞,这也就意味着,他们将在@synchronized()代码块的最后一条语句执行结束后才能继续执行。
@synchronized()指令的唯一参数可以使用任何OC对象,包括self。这个对象就是我们所谓的信号量。这个允许线程锁住一个代码块以防它被别的线程使用。你应当使用不同的信号量来保护程序中不同能够的关键部分。最安全的是,在应用程序进入多线程之前,为所有需要互斥的创建互斥信号量。
以下示例代码展示了一个使用self作为信号量来互斥同步访问当前对象的实例方法。你可以使用同样的方法来同步调用相关联类的类方法,使用类对象,而不是self。在后一种情况(即使用类对象调用类方法),一次只允许一个线程执行一个类方法,因为所有调用对象都使用同一个类对象。
EP1:
- (void)criticalMethod
{
    @synchronized(self) {
       // Critical code.
    }
}


下面的示例使用了当前的selector(翻完了才发现应该是当前执行的方法),_cmd作为信号量。这种同步方式仅在被同步的方法具有唯一名字(即唯一标示符)时有用。在当前方法执行完毕是,不会有其他对象,或者类,会被允许执行一个同样名字的方法。
EP2:
- (void)criticalMethod
{
@synchronized(NSStringFromSelector(_cmd)) { 


// Critical code. ...
 
}
}




下面的示例展示了一个最常用的方法。在执行一个临界线程之前,代码从类Account创建了一个信号量,并使用他锁住临界代码段。这个Account应当在它的initialize方法里面一个信号量。(其实我想说是对信号量初始化)
EP3:
Account *account = [Account accountFromString:[accountField stringValue]];


// Get the semaphore.
  id accountSemaphore = [Account semaphore];


@synchronized(accountSemaphore) {


// Critical code. ...


}


OC的同步特性支持递归和重载方法。一个线程可以使用一个信号量多次,在一个递归的方法。其他线程将被阻塞直到该线程释放所有与他相关的锁。(我的理解就是信号量归零啦)也就是说,每一个@synchronized()块都正常退出或者抛给一个异常。
当代码在一个@synchronized()块中,掷出异常时,OC的运行环境捕获这个异常,释放掉这个信号量(此时被保护的代码可以被其他进程锁执行),然后再次抛掷异常到下一个异常处理。




EP1的测试代码:
 


- (void)testThread{
while (1) {
@synchronized(self){
i=i++;
NSLog(@"%i当前线程名称:%@",i,[[NSThread currentThread] name]);
}
}
}


- (void)startThread{
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(testThread)object:nil];
[thread1 setName:@"线程1"];
[thread1 start];
[thread1 release];
NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(testThread)object:nil];
[thread2 setName:@"线程2"];
[thread2 start];
[thread2 release];
NSThread *thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(testThread)object:nil];
[thread3 setName:@"线程3"];
[thread3 start];
[thread3 release];
}


多个线程同时调用这段代码的时候,执行顺序严格按照线程开启的顺序执行。
下面是部分LOG的记录:
 
 1当前线程名称:线程1
 2当前线程名称:线程2
 3当前线程名称:线程3
 4当前线程名称:线程1
 5当前线程名称:线程2
 6当前线程名称:线程3
 7当前线程名称:线程1
 8当前线程名称:线程2
 9当前线程名称:线程3
 10当前线程名称:线程1
 11当前线程名称:线程2
 12当前线程名称:线程3
 13当前线程名称:线程1
 14当前线程名称:线程2
 15当前线程名称:线程3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值