首页 > 技术文章 > python 并发编程之多线程

kylin5201314 2020-08-25 15:41 原文

一、线程概念

把进程比作车间,

 车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线

      流水线的工作需要电源,电源就相当于cpu

  所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的最小执行单位。

二、线程与进程的区别

如果我们的软件是一个工厂,该工厂有多条流水线,流水线工作需要电源,电源只有一个即cpu(单核cpu)

一个车间就是一个进程,一个车间至少一条流水线(一个进程至少一个线程)

创建一个进程,就是创建一个车间(申请空间,在该空间内建至少一条流水线)

而建线程,就只是在一个车间内造一条流水线,无需申请空间,随之创建开销小

三、开启线程的两种方式

1、例:

 1 # 第一种
 2 # from threading import Thread
 3 # import time
 4 
 5 # def task():
 6 #     print('开始')
 7 #     time.sleep(1)
 8 #     print('结束')
 9 #
10 #
11 # if __name__ == '__main__':
12 #     t=Thread(target=task,) # 实例化得到一个对象
13 #     t.start() # 对象.start()启动线程
14 #     print('主')
15 
16 # 第二种,通过类继承的方式
17 # from threading import Thread
18 # import time
19 # 
20 # class MyThread(Thread):
21 #     def run(self):
22 #         print('开始')
23 #         time.sleep(1)
24 #         print('结束')
25 # 
26 # if __name__ == '__main__':
27 #     t=MyThread()
28 #     t.start()
29 #     print('主')
View Code

四、线程对象join方法

 1 from threading import Thread
 2 
 3 import time
 4 def task(n):
 5     print('开始')
 6     time.sleep(n)
 7     print('结束')
 8 
 9 
10 if __name__ == '__main__':
11     t=Thread(target=task,args=(2,))
12     t.start()
13 
14 
15     t1=Thread(target=task,args=(3,))
16     t1.start()
17 
18 
19     t.join()  # 等待子进程执行结束
20     t1.join()
21     print('')
View Code

五、同一个线程下多个线程数据共享

```python
from threading import Thread

import time

money = 99


def task(n):
    global money
    money=n
    print('开始')
    # time.sleep(n)
    print('结束')


if __name__ == '__main__':
    t = Thread(target=task, args=(2,))
    t.start()

    t1 = Thread(target=task, args=(66,))
    t1.start()


    t.join()
    t1.join()
    print(money)
    print('')

```
View Code

六、线程对象及其他方法

1 线程t.name  t.getName()
2 当前进程下有几个线程存活active_count
3 t1.is_alive() 当前线程是否存活
4 t1.ident  当作是线程id号

七、守护线程

 

from threading import Thread, current_thread,active_count
import time
import os


def task(n):
    print('开始')
    time.sleep(n)
    # print('-----',active_count())
    print('结束')



if __name__ == '__main__':
    t1 = Thread(target=task,name='egon',args=(10,))
    # t1.daemon = True
    t1.setDaemon(True)
    t1.start()

    t2 = Thread(target=task,name='egon',args=(4,))
    t2.start()

    print('')
View Code

八、线程互斥锁

```python
from threading import Thread,Lock
import time
import random

money = 99


def task(n,mutex):
    global money
    # 在修改数据的时候,枷锁
    mutex.acquire()
    temp = money
    time.sleep(0.1)

    money = temp - 1
    # 修改完以后,释放锁,其它线程就能再次抢到锁
    mutex.release()


if __name__ == '__main__':
    ll=[]
    mutex=Lock()
    for i in range(10):
        t = Thread(target=task, args=(i,mutex))
        t.start()
        ll.append(t)

    for i in ll:
        i.join()

    print(money)

```

九、

GIL全局解释器锁理论
```python
#1 python的解释器有很多,cpython,jpython,pypy(python写的解释器)
#2 python的库多,库都是基于cpython写起来的,其他解释器没有那么多的库
#3 cpython中有一个全局大锁,每条线程要执行,必须获取到这个锁
#4  为什么会有这个锁呢?python的垃圾回收机制
#5 python的多线程其实就是单线程
#6 某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行
# 7 总结:cpython解释器中有一个全局锁(GIL),线程必须获取到GIL才能执行,我们开的多线程,不管有几个cpu,同一时刻,只有一个线程在执行(python的多线程,不能利用多核优势)
# 8 如果是io密集型操作:开多线程
# 9如果是计算密集型:开多进程
以上两句话,只针对与cpython解释器

 

推荐阅读