【发布时间】:2014-12-21 05:32:44
【问题描述】:
我有这个方法
- (void) checkIfShouldSendReadingsToServerAsync
{
// Check if I want to send the data
// All other threads should wait hear until I signal them to continue
if (!self.lastSendRequestToServerDateTime ||
([[NSDate date] timeIntervalSinceDate:self.lastSendRequestToServerDateTime]/60.0) > intervalBetweenRequestsToServerInMinutes.doubleValue)
{
// Read data from the SQLite database asynchronous and a completion block
// This call uses a NSOperationQueue block
[self.sqliteStore readingsToSendToServer:^(NSArray *readingsArray)
{
// Loaded the values, now check if I should send them
if (readingsArray &&
readingsArray.count > 0)
{
// Convert array of objects to JSON
NSString* json = [self.sqliteStore readingsArrayToJSON:readingsArray];
// Send the JSON to the server using NSURLSession
[[WEEServiceRepository sharedInstance] sendJSONReadings:json withCompletionHandler:^(NSError *error, NSURLResponse *response)
{
// REST POST call ended, check the status code
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSInteger statusCode = httpResponse.statusCode;
self.lastSendRequestToServerDateTime = [NSDate date];
switch (statusCode)
{
case 200:
case 201:
case 204:
{
// This call uses a NSOperationQueue block
[self.sqliteStore updateReadingsWithSentToServerYes:readingsArray andCompletionBlock:^(BOOL succeed)
{
// Here allow all other threads or the same thread to enter
}];
break;
}
default:
{
// Or here signal to continue
}
}
}];
}
}];
}
}
我希望整个方法是线程安全的,直到服务调用返回并发出信号表明其他线程可以继续执行之前,它应该让它们保持一致。
此代码将在应用程序处于前台但也处于后台时运行。 我尝试了信号量,但一段时间后我发现它在后台停止,可能是死锁?但它不应该!我真的不想使用@synchronized,还是我错了继续尝试?也许只使用 NSLock 或 NSRecursiveLock?
我试图找到最合适的方式来锁定和解锁代码段,尤其是在使用异步方法时。
【问题讨论】:
-
NSLock 是更好的选择
-
看起来是这样,如果我也将此方法包装在 NSOperationQueue 块中并使用 pthread 互斥锁而不是 NSLock 包装器,您会怎么看?我会获得优化和速度吗? Mutex 似乎比 NSLock 快 50%。
-
另外,似乎 NSLock 需要从被锁定的同一个线程中解锁,这在我的情况下是不可能的。
-
这里不完全清楚你在同步什么。也许您可以更新问题中的代码示例,并显示您想象的资源被锁定和解锁的位置。 (您关于从不同线程锁定和解锁的评论让我感到困惑。)就
@synchronized与NSLock而言,这并没有让我觉得有足够的争用很重要,但在这些情况下,自旋锁、GCD 串行队列和读写器模式通常更有效。 -
好的,让我说得更清楚一点,我想锁定读数ToSendToServer:^(NSArray *readingsArray),在我完成 REST 调用和/或更新它们之前,没有人应该阅读这些资源.
标签: ios objective-c multithreading asynchronous