多线程——线程,队列,任务
待填充...
多线程中的线程、队列和任务,这些概念和关系一直不清楚,看了很多文章感觉看懂了但是有时候一思考又混淆了,总是一知半解,下面说说我的理解
任务:
我的理解是一个一个函数就是任务 ,现在又感觉一行代码是一个任务
我们写的那些函数代码经过编译后,会变成...,每个函数会链接下一个函数执行的地址
线程:
线程是一种资源,用于执行队列中的任务
队列:
队列用于管理任务,(CPU?将)队列中的任务分发给线程执行,每个队列(至少)对应一个线程
串行队列:队列中的任务按顺序执行,对应一个线程
并行队列:队列中的任务可以分发给不同的线程同时执行,可以对应多个线程
并行队列中的任务虽然是同时执行,但依然遵循先进先出的原则,先进入队列的任务先移出队列,即使后面的任务先执行完也要等待前面的任务
如果当前调度的任务是同步执行的,会等待任务执行完成后,再调度后续的任务
如果当前调度的任务是异步执行的,同时底层线程池有可用的线程资源,会再新的线程调度后续任务的执行
主队列
特点:
专门用来在主线程上调度任务的队列
不会开启线程
以先进先出的方式,在主线程空闲时才会调度队列中的任务在主线程执行
如果当前主线程正在有任务执行,那么无论主队列中当前被添加了什么任务,都不会被调度
队列获取:
主队列是负责在主线程调度任务的
会随着程序启动一起创建
主队列只需要获取不用创建
以下看到一个帖子,关于多线程队列的,值得记下
网址http://www.cocoachina.com/bbs/read.php?tid-1738170-page-1.html
Q:
GCD小菜,以前计算机原理说,线程是CPU调度的基本单位,那么GCD的block肯定是运行在某个线程上的,
直到我看到了下面这段代码....居然不会死锁??!!
#import
int main(int argc, const char * argv[]) {
dispatch_queue_t queue_t = dispatch_queue_create("myConsoleQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue_t, ^{
NSLog(@"1. current thread = %@", [NSThread currentThread]);
});
NSLog(@"2. current thread = %@", [NSThread currentThread]);
return 0;
}
还看了http://www.cocoachina.com/ios/20160802/17259.html这篇文章,
突然觉得好像GCD的死锁不是跟线程相关的,而是跟队列有关的(向当前队列重复同步提交 block)。
看完这篇文章的解释,我并不能完全理解,相反线程死锁的概念在我的世界观中频临崩溃,还强加了一些队列的概念在里面。
究竟GCD里线程和队列是一种什么关系,有人能解释清楚吗。
A1:
你错误地理解了线程与队列的关系,队列上是放任务的,而线程是去执行队列上的任务的,为什么你的代码不会死锁.我们一步步地去分析.
dispatch_queue_t queue_t = dispatch_queue_create("myConsoleQueue", DISPATCH_QUEUE_SERIAL);这句代码的意思是我在主队列上放一个任务,任务是创建了一个串行队列
dispatch_sync(queue_t, ^{
NSLog(@"1. current thread = %@", [NSThread currentThread]);
});这句代码的意思是,我在主队列上放一个任务,任务是将一个同步任务放在我们的queue_t的串行队列上.学过GCD的应该都要知道,同步任务放在串行队列上是不开辟线程的(由当前线程执行,代码中显而易见,由主线程去执行),这时候主队列会卡住,因为主队列在等待这个dispatch_sync的返回值.然后主线程青睐了你的串行队列queue_t,执行了NSLog(@"1. current thread = %@", [NSThread currentThread]);这个任务后,dispatch_sync返回了一个值.主队列不会卡住,这时候主线程再青睐了主队列后,又能继续往下走了.
????所以你的这句代码是非常危险的,如果你的同步任务不是 NSLog(@"1. current thread = %@", [NSThread currentThread]);而是一个耗时操作,你的主队列会一直在等待同步任务的返回值,在任务结束前,你点UI是没有任何反应的.
A2:这时候主队列会卡住,为什么是主队列卡住,而不是主线程卡住,当前不是在主线程上运行吗?
当前有一个主线程,有一个主队列和一个串行队列,队列的任务是放到主线程上去执行的,因为它是CPU调度的基本单位,当前主线程卡住了,然后怎么在当前主线程上再去调度别的队列的block。
A3:在没有GCD队列的概念之前,我知道要线程同步等待的任务,必然是其它线程去执行的,自己等待自己去执行必然是会引起死锁,没有遇到这段代码之前我对GCD的理解都是很美好的,现在我突然开始有点疑惑了。
我的理解是:主线程会在循环里执行主队列和串行队列的任务(block), 现在主队列的block卡住了,必然会导致主线程被卡住,除非队列的block执行有一种超时机制,超时后再去执行跟它同级的串行队列的任务(这里是由于同步等待导致的超时),但是这个超时时间也是一个很值得考究的问题,当然这只是我一种猜测,感觉这样可以解释得通,但是有点牵强,实在是不敢带着这种疑惑去猜测和写代码。
A4:主线程不会卡的,只会在多个队列上来回切换.只是主队列的优先级比较高,如果queue_t是主队列,那么你的代码将会死锁
A5:死锁说的就是线程死锁,队列,不管是串行队列还是并行队列都是fifo 根本谈不上锁的概念,也就更谈不上死锁
线程和队列完全就是完全不搭边的两个概念,线程就是你cpu的处理能力,队列就是一个任务容器,cpu从容器中取出任务,然后放到线程去执行 ,他俩之间就这点联系
分析你这段代码,实际上是一个线程(主线程) 2个队列(主队列、queue_t)
1、主线程首先执行主队列的任务 dispatch_queue_t queue_t = dispatch_queue_create("myConsoleQueue", DISPATCH_QUEUE_SERIAL);
2、主线程继续执行 dispatch_sync(queue_t, ^{
3、主线程执行 queue_t 任务,也就是里面的两个nslog
4、主线程 执行完毕 queue_t 任务 任务之后切回 主队列继续执行主队列任务(已经没有了)
A6:大佬你好,你说线程和队列是完全不搭边的概念,虽然你这么说,但我还是没能理解好上述代码的执行过程,他们之间是怎么协作而不会产生死锁的,更具体点的问题如下:
1.队列锁住为什么不会造成线程锁住?(这是怎么实现的?)。
2.在没有队列概念的情况下,main函数就是在主线程上执行,现在变成了main函数就是主队列的一个任务了?也就是说最简单的console程序,都会启动一个主线程(这是毋容置疑的),然后创建主队列,把main函数当作主队列的block任务,放到主线程中执行,然后添加到其它串行队列的任务也会放到主线程上执行?是不是时间片的概念从线程上,下放到队列上了,我可以这样理解吗?
PS:以前看书说gcd队列是需要从操作系统级别实现的,不是简单的一个C语言实现的库,但是gcd是开源的,好像也可以拿到linux上编译使用。