我正在尝试使用线程和NSCondition在Swift 2中实现生产者/消费者类。到目前为止,我已经提出了这个代码:
import Foundation
class ProducterConsumer {
private let numberOfProducts = 1000
private var products: [Int] = []
private var condition = NSCondition()
private func producer() {
for var i = 0; i < numberOfProducts; ++i {
condition.lock()
products.append(i)
condition.broadcast()
condition.unlock()
}
}
private func consumer(id: Int) {
while true {
condition.lock()
while products.count == 0 {
condition.wait()
}
let product = products.popLast()!
print("[\(id)] takes \(product)")
condition.unlock()
}
}
func runAndWait() {
let queue = NSOperationQueue()
for var i = 0; i < 2; ++i {
queue.addOperationWithBlock {
self.consumer(i)
}
}
queue.addOperationWithBlock {
self.producer()
}
queue.waitUntilAllOperationsAreFinished()
}
}
let pc = ProducterConsumer()
pc.runAndWait()
基本上我正在使用操作队列创建3个新线程:1个生成器填充Int
的共享数组(从0到1000)和2个弹出值并显示它们的消费者。
结果显示只有消费者线程#0“有效”并且似乎是弹出值。我无法弄清楚为什么消费者线程#1不会在控制台中显示。我预计两个消费者之间或多或少会有50%的工作时间。我缺少什么?
[0] takes 0
[0] takes 1
...
[0] takes 998
[0] takes 999
谢谢!
答案 0 :(得分:1)
问题似乎是lazy var
is not thread-safe,您的代码甚至在我的测试中崩溃,并显示错误消息,如
*** -[NSCondition dealloc]: condition (<NSCondition: 0x10080b310> '(null)') deallocated while still in use
*** Break on _NSLockError() to debug.
*** -[NSCondition wait]: condition (<NSCondition: 0x100e00920> '(null)') not locked
*** -[NSCondition unlock]: condition (<NSCondition: 0x100e00920> '(null)') unlocked from thread which did not lock it
如您所见,(至少)有两种不同的NSCondition
实例
如果您将属性更改为
private var condition = NSCondition()
然后在ProducterConsumer()
时创建单个条件变量
实例已创建,一切都按预期运行。
另一个问题是
for var i = 0; i < 2; ++i {
queue.addOperationWithBlock {
self.consumer(i)
}
}
该块通过引用捕获变量i
。因此
即使是不同的运行线程也可以报告相同的数字i
。
要按值捕获变量,请使用显式捕获列表:
for var i = 0; i < 5; ++i {
queue.addOperationWithBlock { [i] in
self.consumer(i)
}
}
我还建议在多线程程序中使用NSLog()
进行调试输出,因为
NSLog()
和相比,print()
是线程安全的
NSLog()
打印进程ID和线程ID,以便您可以
验证输出是否来自不同的线程。例如:
2015-11-09 15:21:43.711 MyProgram[8569:537106] [0] takes 19
2015-11-09 15:21:43.788 MyProgram[8569:537108] [2] takes 18
答案 1 :(得分:0)
我稍微修改你的消费者阻止(NSOperation)
private func consumer(id: Int) {
while true {
condition.lock()
while products.count == 0 {
condition.wait()
}
let product = products.popLast()!
condition.unlock()
NSLog("[\(id)] takes \(product)")
usleep(500000)
}
}
检查NSLog报告的内容
2015-11-09 20:26:06.249 Untitled Page 10[90128:4829072] [0] takes 0
2015-11-09 20:26:06.262 Untitled Page 10[90128:4829076] [1] takes 1
2015-11-09 20:26:06.760 Untitled Page 10[90128:4829072] [0] takes 9
2015-11-09 20:26:06.783 Untitled Page 10[90128:4829076] [1] takes 8
2015-11-09 20:26:07.272 Untitled Page 10[90128:4829072] [0] takes 7
2015-11-09 20:26:07.295 Untitled Page 10[90128:4829076] [1] takes 6
2015-11-09 20:26:07.775 Untitled Page 10[90128:4829072] [0] takes 5
2015-11-09 20:26:07.803 Untitled Page 10[90128:4829076] [1] takes 4
2015-11-09 20:26:08.282 Untitled Page 10[90128:4829072] [0] takes 3
2015-11-09 20:26:08.311 Untitled Page 10[90128:4829076] [1] takes 2
特别是消费者消费的价值顺序。
NSCondition对象在给定线程中充当锁和检查点。
您不应该依赖队列语义来确保操作对象的特定执行顺序
产品数量100 消费者数量20 没有延误
2015-11-09 21:16:04.687 Untitled Page 10[90457:4863959] [0] takes 0
2015-11-09 21:16:04.692 Untitled Page 10[90457:4863915] [1] takes 1
2015-11-09 21:16:04.695 Untitled Page 10[90457:4863916] [2] takes 2
2015-11-09 21:16:04.713 Untitled Page 10[90457:4863966] [3] takes 3
2015-11-09 21:16:04.720 Untitled Page 10[90457:4863915] [1] takes 4
2015-11-09 21:16:04.745 Untitled Page 10[90457:4863915] [1] takes 5
2015-11-09 21:16:04.754 Untitled Page 10[90457:4863915] [1] takes 6
2015-11-09 21:16:04.758 Untitled Page 10[90457:4863915] [1] takes 7
2015-11-09 21:16:04.761 Untitled Page 10[90457:4863915] [1] takes 8
2015-11-09 21:16:04.780 Untitled Page 10[90457:4863915] [1] takes 9
2015-11-09 21:16:04.788 Untitled Page 10[90457:4863915] [1] takes 10
2015-11-09 21:16:04.795 Untitled Page 10[90457:4863915] [1] takes 11
2015-11-09 21:16:04.800 Untitled Page 10[90457:4863915] [1] takes 12
2015-11-09 21:16:04.805 Untitled Page 10[90457:4863915] [1] takes 13
2015-11-09 21:16:04.812 Untitled Page 10[90457:4863925] [14] takes 14
2015-11-09 21:16:04.816 Untitled Page 10[90457:4863925] [14] takes 15
2015-11-09 21:16:04.823 Untitled Page 10[90457:4863979] [16] takes 16
2015-11-09 21:16:04.828 Untitled Page 10[90457:4863979] [16] takes 17
2015-11-09 21:16:04.833 Untitled Page 10[90457:4863980] [18] takes 18
2015-11-09 21:16:04.838 Untitled Page 10[90457:4863980] [18] takes 19
2015-11-09 21:16:04.843 Untitled Page 10[90457:4863980] [18] takes 20
2015-11-09 21:16:04.847 Untitled Page 10[90457:4863980] [18] takes 21
2015-11-09 21:16:04.853 Untitled Page 10[90457:4863966] [3] takes 22
2015-11-09 21:16:04.860 Untitled Page 10[90457:4863967] [4] takes 23
2015-11-09 21:16:04.866 Untitled Page 10[90457:4863967] [4] takes 24
2015-11-09 21:16:04.871 Untitled Page 10[90457:4863967] [4] takes 25
2015-11-09 21:16:04.877 Untitled Page 10[90457:4863967] [4] takes 26
2015-11-09 21:16:04.882 Untitled Page 10[90457:4863967] [4] takes 27
2015-11-09 21:16:04.887 Untitled Page 10[90457:4863967] [4] takes 28
2015-11-09 21:16:04.893 Untitled Page 10[90457:4863973] [10] takes 29
2015-11-09 21:16:04.900 Untitled Page 10[90457:4863974] [11] takes 30
2015-11-09 21:16:04.906 Untitled Page 10[90457:4863975] [12] takes 31
2015-11-09 21:16:04.911 Untitled Page 10[90457:4863976] [13] takes 32
2015-11-09 21:16:04.916 Untitled Page 10[90457:4863976] [13] takes 33
2015-11-09 21:16:04.921 Untitled Page 10[90457:4863926] [15] takes 34
2015-11-09 21:16:04.927 Untitled Page 10[90457:4863926] [15] takes 35
2015-11-09 21:16:04.932 Untitled Page 10[90457:4863926] [15] takes 36
2015-11-09 21:16:04.936 Untitled Page 10[90457:4863979] [16] takes 37
2015-11-09 21:16:04.939 Untitled Page 10[90457:4863981] [19] takes 38
2015-11-09 21:16:04.947 Untitled Page 10[90457:4863981] [19] takes 39
2015-11-09 21:16:04.953 Untitled Page 10[90457:4863916] [2] takes 40
2015-11-09 21:16:04.956 Untitled Page 10[90457:4863980] [18] takes 41
2015-11-09 21:16:04.962 Untitled Page 10[90457:4863966] [3] takes 42
2015-11-09 21:16:04.970 Untitled Page 10[90457:4863966] [3] takes 43
2015-11-09 21:16:04.974 Untitled Page 10[90457:4863969] [6] takes 44
2015-11-09 21:16:04.978 Untitled Page 10[90457:4863969] [6] takes 45
2015-11-09 21:16:04.983 Untitled Page 10[90457:4863969] [6] takes 46
2015-11-09 21:16:04.987 Untitled Page 10[90457:4863969] [6] takes 47
2015-11-09 21:16:04.994 Untitled Page 10[90457:4863969] [6] takes 48
2015-11-09 21:16:04.999 Untitled Page 10[90457:4863973] [10] takes 49
2015-11-09 21:16:05.005 Untitled Page 10[90457:4863973] [10] takes 50
2015-11-09 21:16:05.012 Untitled Page 10[90457:4863973] [10] takes 51
2015-11-09 21:16:05.020 Untitled Page 10[90457:4863973] [10] takes 52
2015-11-09 21:16:05.026 Untitled Page 10[90457:4863973] [10] takes 53
2015-11-09 21:16:05.033 Untitled Page 10[90457:4863925] [14] takes 54
2015-11-09 21:16:05.037 Untitled Page 10[90457:4863925] [14] takes 55
2015-11-09 21:16:05.060 Untitled Page 10[90457:4863925] [14] takes 56
2015-11-09 21:16:05.065 Untitled Page 10[90457:4863925] [14] takes 57
2015-11-09 21:16:05.072 Untitled Page 10[90457:4863925] [14] takes 58
2015-11-09 21:16:05.082 Untitled Page 10[90457:4863981] [19] takes 59
2015-11-09 21:16:05.084 Untitled Page 10[90457:4863916] [2] takes 60
2015-11-09 21:16:05.093 Untitled Page 10[90457:4863980] [18] takes 61
2015-11-09 21:16:05.100 Untitled Page 10[90457:4863968] [5] takes 62
2015-11-09 21:16:05.107 Untitled Page 10[90457:4863966] [3] takes 63
2015-11-09 21:16:05.111 Untitled Page 10[90457:4863966] [3] takes 64
2015-11-09 21:16:05.119 Untitled Page 10[90457:4863966] [3] takes 65
2015-11-09 21:16:05.124 Untitled Page 10[90457:4863966] [3] takes 66
2015-11-09 21:16:05.129 Untitled Page 10[90457:4863967] [4] takes 67
2015-11-09 21:16:05.135 Untitled Page 10[90457:4863967] [4] takes 68
2015-11-09 21:16:05.139 Untitled Page 10[90457:4863974] [11] takes 69
2015-11-09 21:16:05.144 Untitled Page 10[90457:4863975] [12] takes 70
2015-11-09 21:16:05.152 Untitled Page 10[90457:4863915] [1] takes 71
2015-11-09 21:16:05.156 Untitled Page 10[90457:4863976] [13] takes 72
2015-11-09 21:16:05.160 Untitled Page 10[90457:4863976] [13] takes 73
2015-11-09 21:16:05.211 Untitled Page 10[90457:4863976] [13] takes 74
2015-11-09 21:16:05.220 Untitled Page 10[90457:4863976] [13] takes 75
2015-11-09 21:16:05.224 Untitled Page 10[90457:4863976] [13] takes 76
2015-11-09 21:16:05.235 Untitled Page 10[90457:4863976] [13] takes 77
2015-11-09 21:16:05.237 Untitled Page 10[90457:4863925] [14] takes 78
2015-11-09 21:16:05.243 Untitled Page 10[90457:4863981] [19] takes 79
2015-11-09 21:16:05.250 Untitled Page 10[90457:4863981] [19] takes 80
2015-11-09 21:16:05.255 Untitled Page 10[90457:4863981] [19] takes 81
2015-11-09 21:16:05.261 Untitled Page 10[90457:4863981] [19] takes 82
2015-11-09 21:16:05.268 Untitled Page 10[90457:4863981] [19] takes 83
2015-11-09 21:16:05.273 Untitled Page 10[90457:4863981] [19] takes 84
2015-11-09 21:16:05.278 Untitled Page 10[90457:4863981] [19] takes 85
2015-11-09 21:16:05.284 Untitled Page 10[90457:4863981] [19] takes 86
2015-11-09 21:16:05.291 Untitled Page 10[90457:4863981] [19] takes 87
2015-11-09 21:16:05.296 Untitled Page 10[90457:4863981] [19] takes 88
2015-11-09 21:16:05.299 Untitled Page 10[90457:4863974] [11] takes 89
2015-11-09 21:16:05.305 Untitled Page 10[90457:4863974] [11] takes 90
2015-11-09 21:16:05.310 Untitled Page 10[90457:4863974] [11] takes 91
2015-11-09 21:16:05.317 Untitled Page 10[90457:4863974] [11] takes 92
2015-11-09 21:16:05.322 Untitled Page 10[90457:4863978] [17] takes 93
2015-11-09 21:16:05.327 Untitled Page 10[90457:4863978] [17] takes 94
2015-11-09 21:16:05.333 Untitled Page 10[90457:4863978] [17] takes 95
2015-11-09 21:16:05.338 Untitled Page 10[90457:4863978] [17] takes 96
2015-11-09 21:16:05.343 Untitled Page 10[90457:4863978] [17] takes 97
2015-11-09 21:16:05.348 Untitled Page 10[90457:4863978] [17] takes 98
2015-11-09 21:16:05.353 Untitled Page 10[90457:4863978] [17] takes 99