2017-10-05 142 views
1

试图使线程安全的数组,但它的工作原理并不如我所料DispatchQueue障碍问题

import Foundation 
import PlaygroundSupport 

PlaygroundPage.current.needsIndefiniteExecution = true 

public class SafeArray<Element> { 
    private var array = [Element]() 
    private let queue = DispatchQueue(label: "queueBarrier", attributes: .concurrent) 

    public func append(element: Element) { 
     queue.async(flags: .barrier) { 
      self.array.append(element) 
     } 
    } 

    public var elements: [Element] { 
     var result = [Element]() 
     queue.sync { 
      result = self.array 
     } 
     return result 
    } 

    public var last: Element? { 
     var result: Element? 
     queue.sync { 
      result = self.array.last 
     } 
     return result 
    } 
} 




var safeArray = SafeArray<Int>() 
var array = Array<Int>() 

DispatchQueue.concurrentPerform(iterations: 10) { (int) in 
    let last = array.last ?? 0 
    array.append(last + 1) 
    print("array = [..\(last)]") 
} 

print(array) 

DispatchQueue.concurrentPerform(iterations: 10) { (int) in 
    let last = safeArray.last ?? 0 
    safeArray.append(element: last + 1) 
     print("safeArray = [..\(last)]") 
} 

print(safeArray.elements) 

output of my code

我预计阵列应该有一些混乱,但SAFEARRAY应该有一个数字从0到9

据我所知,array有3个值,但safeArray有10个值按预期。但为什么这个值不是从0到9?

谢谢!

回答

0

不,你不会得到价值形态1 - 10 !!!,由于DispatchQueue.concurrentPerform执行多个操作的同时

让我解释一下

假设DispatchQueue.concurrentPerform将同时执行3项,然后这里

let last = safeArray.last ?? 0 

你会得到0三次然而它是通过增加1其追加数组,以便

您的数组变得像[1,1,1 ...]

有巴里在这里输出的还是我没有清算角色

尽管屏障进程正在运行,但读者仍然会被阻止。即使有并行已经运行几个读者块,屏障进程将等待所有的读者开始写

如果您需要阻止行为,你应该使用DispatchSemaphoreMjZac解释之前完成

希望你明白

0

为什么不使用DispatchSemaphore

import Foundation 
import PlaygroundSupport 

PlaygroundPage.current.needsIndefiniteExecution = true 

public class SafeArray<Element> { 
    private var array = [Element]() 
    private let semaphore = DispatchSemaphore(value: 1) 
    private var lastEl: Element? 

    public func append(element: Element) { 

      self.array.append(element) 
    } 

    public var elements: [Element] { 
     var result = [Element]() 
     result = self.array 
     return result 
    } 

    public var last: Element? { 
     self.semaphore.wait() 
     lastEl = self.array.last 
     self.semaphore.signal() 
     return lastEl 
    } 
} 




var safeArray = SafeArray<Int>() 
var array = Array<Int>() 

DispatchQueue.concurrentPerform(iterations: 10) { (int) in 
    let last = array.last ?? 0 
    array.append(last + 1) 
    print("array = [..\(last)]") 
} 

print(array) 

DispatchQueue.concurrentPerform(iterations: 10) { (int) in 
    let last = safeArray.last ?? 0 
    safeArray.append(element: last + 1) 
    print("safeArray = [..\(last)]") 
} 

print(safeArray.elements)