var list: [Int] = []
public func printListValues() {
DispatchQueue.global().async {
while true {
if self.list.count < 10 {
self.list.append(self.list.count)
} else {
self.list.removeAll()
}
}
}
DispatchQueue.global().async {
while true {
let newList = self.list
newList.forEach { debugPrint($0) }
}
}
}
我知道有时数组不是线程安全的。但是我做了let value = self.list
。而且它还会崩溃并显示以下信息:
线程3:致命错误:索引超出范围
在newList.forEach { debugPrint($0) }
行上。
为什么newList
不安全。有什么问题吗?
答案 0 :(得分:2)
数组操作不是原子的。当您在第二个线程中访问数组时,必须确保它不在第一个线程上的append()或removeAll()操作的中间,否则您可能正在复制处于不确定状态的数组。类似地,这两个操作之一可能发生在数组复制操作的中间,这会导致在复制数组时更改状态的问题。您可以通过添加一些线程同步来修复代码。
var list: [Int] = []
var mutex = pthread_mutex_t()
public func printListValues() {
pthread_mutex_init(&mutex, nil)
DispatchQueue.global().async {
while true {
if self.list.count < 10 {
pthread_mutex_lock(&self.mutex)
self.list.append(self.list.count)
pthread_mutex_unlock(&self.mutex)
} else {
pthread_mutex_lock(&self.mutex)
self.list.removeAll()
pthread_mutex_unlock(&self.mutex)
}
}
}
DispatchQueue.global().async {
while true {
pthread_mutex_lock(&self.mutex)
let newList = self.list
pthread_mutex_unlock(&self.mutex)
newList.forEach { debugPrint($0) }
}
}
}
答案 1 :(得分:2)
@Spads提供了有关该问题的大量信息(尽管我将使用GCD而不是pthread来解决该问题),但它提出了一个问题,即如果您没有立即发现问题,则如何发现此问题。答案是Thread Sanitizer,它将直接指向您的问题所在。这是方案的一项设置(或者您可以直接将extractData
传递到 function this = extractData(this, xAxis, yAxis)
s = dir('*.txt'); % Gather all text files
disp(length(s))
for i=1:length(s) % Loop through and gather data until last element of strcuct
j = 1;
fid = s(i).name; % Open file in read-only mode
this = this.readDataFromFile(fid);
disp(fid)
x = this.metaData(find(contains(this.metaData(:,1), xAxis)),3);
this.temp(i,j) = x;
disp(this.temp(i,j))
j = j+1;
y = this.metaData(find(contains(this.metaData, yAxis)),3); %#ok<*FNDSB>
this.temp(i,j) = y;
disp(this.temp(i,j))
end %for
end %extractData
)。
设置完成后,您将在Xcode中获得以下内容,直接将您指向冲突的行。