谈到线程同步,一般指如何对线程间共享数据的同步读写,如何避免混乱的读写结果。一个基本的解决办法就是使用锁(LOCK)。
iOS提供多种同步锁的类和方法,这里介绍下基本用法。
1. NSLock:最基本的同步锁,使用lock来获得锁,unlock释放锁。如果其它线程已经使用lock,这时lock方法会阻塞当前线程,直到其它线程调用unlock释放锁为止。NSLock锁一般用于简单的同步算法。比如生产者线程产生数据(produce),消费线程显示数据(consume),可以这样实现:
- (void)produce
{
while (1)
{
[theLock lock];
// create data
[theLock unlock];
}
}
- (void)consume
{
while (1)
{
if ([theLock tryLock])
{
// display data
[theLock unlock];
}
sleep(1.0); //sleep a while
}
}
NSLock的tryLock方法可以避免阻塞当前线程,如果不能获得锁则返回NO。也可使用:
- (BOOL)lockBeforeDate:(NSDate *)limit;
设置超时返回时间。
2. NSConditionLock,即条件锁,可以设置自定义的条件来获得锁。比如上面的例子可以这样改用条件锁实现:
- (void)produce
{
while (1)
{
[theLock lockWhenCondition:NO_DATA];
// create data
[theLock unlockWithCondition:HAS_DATA];
}
}
- (void)consume
{
while (1)
{
if ([theLock tryLockWhenCondition:HAS_DATA])
{
// display data
[theLock unlockWithCondition:NO_DATA];
}
sleep(1.0); //sleep a while
}
}
3. NSCondition:条件(一种信号量),类似Java中的Condition,但有所不同的是NSCondition是锁和条件的组合实现。wait方法用于线程的等待(相当于Java Condition的await()),然后通过signal方法通知等待线程(相当于Java Condition的signal()),或者broadcast通知所有等待的线程相当于Java Condition的signalAll())。一个简单生产消费同步例子:
- (void)produce
{
[theLock lock];
// create data
hasData = YES;
[theLock signal]; //这时通知调用wait的线程结束等待并返回
[theLock unlock];
}
- (void)consume
{
[theLock lock];
while (!hasData)
[theLock wait]; //注意:这时其它线程的lock调用会成功返回
//display data
hasData = NO;
[theLock unlock];
}
4. NSRecursiveLock:递归锁,顾名思义一般用于递归程序。它可以让同一线程多次获得锁,解锁次数也必须相同,然后锁才能被其它线程获得。看下官网文档中的简单例子就能明白:
void MyRecursiveFunction(int value)
{
[theLock lock];
if (value != 0)
{
--value;
MyRecursiveFunction(value);
}
[theLock unlock];
}
当然不只用于递归程序,类似Java中的ReentrantLock。
5. @synchronized实现对象锁,类似Java中synchronized关键词。一般这样使用,但不多啰嗦了:
@synchronized(anObj)
{
//......
}