死锁问题(Dead Lock):指两个或两个以上的线程,它们之间互相等待彼此停止执行,以获得某种资源,但是没有一方会提前退出的情况

1.操作互相依赖造成死锁

let a = BlockOperation.init {
    print("4")
}
let b = BlockOperation.init {
    print("5")
}
a.addDependency(b)
b.addDependency(a)
b.start()
a.start()
print("死锁")

2.在主线程中,使用同步操作是一定会构成死锁

// 当前线程是主线程
print("1")
DispatchQueue.main.sync {
    print("2")
}
print("3")

思考:如果当前线程是异步线程,那么以上代码还会发生死锁吗?

print("1")
DispatchQueue.global().async {
    DispatchQueue.main.sync {
        print(Thread.current) // 主线程
        print("2")
    }
    print("3")
}

不会发生死锁 执行顺序,一定是123,不会出现132,因为sync同步会阻塞线程

在思考以下

// 当前线程为主线程
print("1")
DispatchQueue.global().async {
    DispatchQueue.main.async {
        print(Thread.current) // 主线程
        print("2")
    }
    print("3")
}

执行顺序为123或者是132

3.同一个串行队列中进行异步、同步嵌套会构成死锁

let serialQueue = DispatchQueue.init(label: "serial")
serialQueue.async {
    print(Thread.current) // 打印是子线程
    serialQueue.sync {
        print("888888")
        print("99999")
    }
}

因为串行队列一次只能执行一个任务,所以首先它会把异步 block 中的任务派发执行,当进入到 block 中时,同步操作意味着阻塞当前队列 。而此时外部 block 正在等待内部 block 操作完成,而内部block 又阻塞其操作完成,即内部 block 在等待外部 block 操作完成。所以串行队列自己等待自己释放资源,构成死锁

4.信号量乱用

demo

串行与并行(针对的是队列)

在使用GCD的时候,我们会把需要处理的任务放到Block中,然后将任务追加到相应的队列里面,这个队列,叫做Dispatch Queue。然而,存在于两种Dispatch Queue,一种是要等待上一个执行完,再执行下一个的Serial Dispatch Queue,这叫做串行队列;另一种,则是不需要上一个执行完,就能执行下一个的Concurrent Dispatch Queue,叫做并行队列。这两种,均遵循FIFO原则。

举一个简单的例子,在三个任务中输出1、2、3,串行队列输出是有序的1、2、3,但是并行队列的先后顺序就不一定了。

同步与异步(针对的是线程)

同步线程要阻塞当前线程,必须要等待同步线程中的任务执行完,返回以后,才能继续执行下一任务;而异步线程则是不用等待。 同步就是为了防止多个线程抢夺同一个资源造成的数据安全问题

并发和并行(iOS多线程一般指的是并发)

并发(Concurrent):在固定时间内可以执行多个任务。注意,它和并行(Parallel)的区别在于,并发不会同时执行多个任务,而是通过在任务间不断切换去完成所有工作