我一直在考慮一個看起來很容易實現的問題,但一個高效且線程安全的解決方案阻礙了我的發展。我想要做的是創建某種工作對象。幾個呼叫者可能會要求它從不同的線程工作。一個要求是請求不能排隊。換句話說,如果有人要求工作人員做工,但看到工作已經開始,那麼應該早點回來。關於使這個線程安全,但有效的建議?
一個簡單的第一階段是這樣的:
@interface Worker : NSObject
@property (nonatomic, assign, getter = isWorking) BOOL working;
- (void)doWork;
@end
@implementation Worker
{
dispatch_queue_t _workerQueue; //... a private serial queue
}
- (void)doWork
{
if (self.isWorking)
{
return;
}
self.working = YES;
dispatch_async(_workerQueue, ^{
// Do time consuming work here ... Done!
self.working = NO;
});
}
@end
這樣做的問題是,isWorking屬性不是線程安全的。將它標記爲原子將不會有幫助,因爲對它的訪問需要在幾條語句中同步。
爲了讓線程安全的,我需要保護isWorking用鎖:
@interface Worker : NSObject
@property (nonatomic, assign, getter = isWorking) BOOL working;
- (void)doWork;
@end
@implementation Worker
{
dispatch_queue_t _workerQueue; //... a private serial queue
NSLock *_lock; // assume this is created
}
- (void)doWork
{
[_lock lock];
if (self.isWorking)
{
[_lock unlock];
return;
}
self.working = YES;
[_lock unlock];
dispatch_async(_workerQueue, ^{
// Do time consuming work here ... Done!
[_lock lock];
self.working = NO;
[_lock unlock];
});
}
@end
雖然我相信這將是線程安全的,我認爲這是非常糟糕到必須採取並經常放棄鎖定(昂貴的操作)。
那麼,有沒有更優雅的解決方案?
不錯。我開始自己走上這條路。然而,讓外部人員工作的財產問問並看看工作人員是否工作仍然會很好。如果我想,看起來我仍然需要找到一種讀取或寫入原子的方式。 –
似乎那財產不可靠,不是嗎?當你給一個調用者返回一個值時,它可能會過時。無論如何,你總是可以:'if(dispatch_semaphore_wait(_semaphore,DISPATCH_TIME_NOW)== 0){isWorking = NO; dispatch_semaphore_signal(_semaphore); } else {isWorking = YES; }'。 –
你說得很好,我同意。我猜想我只是在想假設,如果一個外部調用者想問工人和工作人員是否正在改變isWorking的價值,那麼我只是感興趣,如果單獨是線程安全的還是競爭條件的話。 –