首页 > 解决方案 > 分配的空间不足,无法复制数组内容

问题描述

我正在构建一些代码来从数据库中请求多个信息,以便在我的前端包括一个时间表。多个数据库请求。

问题在于,对于一​​个特定的请求,其中 . 我正在使用 swiftKuery 和 DispatchGroups,我偶尔会在 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 中完成更早的执行???但这是我唯一的想法......

标签: arraysswift

解决方案


这很可能是由一些竞争条件引起的,因为您从多个线程修改了数组。如果两个线程碰巧同时尝试改变数组,你就会遇到问题。

确保序列化对数组的访问,这应该可以解决问题。您可以为此使用信号量:

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()

这里的信号量就像一个互斥体,最多允许一个线程对数组进行操作。另外我想强调一个事实,即锁应该保持尽可能少的时间,这样其他线程就不必等待太多。


推荐阅读