我正在构建一些代码来请求数据库中的多个信息,以便在前端有一个时间表,包括多个数据库请求。
问题是在一个特定的请求中。在使用swiftKuery和DispatchGroups时,我会收到ooccasionly,但并不总是在XCode中收到错误消息。这不能通过不同的请求重建,但有时会发生。
这是我的一段代码。
var profWorkDaysBreak = [time_workbreaks]()
let groupServiceWorkDayBreaks = DispatchGroup()
...
///WorkdaysBreakENTER AsyncCall
//UnreliableCode ?
profWorkDays.forEach {workDay in
groupServiceWorkDayBreaks.enter()
time_workbreaks.getAll(weekDayId: workDay.id) { results, error in
if let error = error {
print(error)
}
if let results = results {
profWorkDaysBreak.append(contentsOf: results) // The error happens here !
}
groupServiceWorkDayBreaks.leave()
}
}
...
groupServiceWorkDayBreaks.wait()
结果和profWorkDaysBreak变量是相同的,只是有时我收到消息:
致命错误:分配给复制数组内容的空间不足
这导致了死刑的终止。
我想,循环有时可能会在DispatchGroup中完成先前的执行??? 但这是我唯一的想法。。。。
最佳答案
这很可能是由于某些争用条件造成的,因为您可以从多个线程修改数组。如果两个线程同时尝试改变数组,就会出现问题。
确保序列化对数组的访问,这将解决问题。您可以使用信号量:
var profWorkDaysBreak = [time_workbreaks]()
let groupServiceWorkDayBreaks = DispatchGroup()
let semaphore = DispatchSemaphore(value: 0)
...
profWorkDays.forEach { workDay in
groupServiceWorkDayBreaks.enter()
time_workbreaks.getAll(weekDayId: workDay.id) { results, error in
if let error = error {
print(error)
}
if let results = results {
// acquire the lock, perform the non-thread safe operation, release the lock
semaphore.wait()
profWorkDaysBreak.append(contentsOf: results) // The error happens here !
semaphore.signal()
}
groupServiceWorkDayBreaks.leave()
}
}
...
groupServiceWorkDayBreaks.wait()
这里的信号量就像一个互斥锁,最多允许一个线程对数组进行操作。另外,我想强调一个事实,即锁应该被保持尽可能短的时间,这样其他线程就不必等待太久。