python多线程
来源:互联网 发布:西安鼓楼网络售票 编辑:程序博客网 时间:2024/05/17 13:07
**
什么是线程?
**
线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。(维基百科)
上面的解释很抽象吧,我再解释一下。当一个程序启动时,就会产生一个进程或者多个进程,当一个进程产生,同时也会产生一个进程,这个进程就是主进程。而主进程还会产生子进程,这些子进程是可以同时进行的。
例如,有两个这样的程序:
def a(): print('第一个函数')def b(): print('第二个函数')a()b()
上面的程序先执行函数a(),再执行函数b()。如果要用到进程的话,函数a()和函数b()可以同时进行。
**
python中的进程
**
python提供了threading模块进行进程的调控。我们把上面的那段程序改写成多进程的:
import threadingdef a(): print('第一个函数\n')def b(): print('第二个函数\n')th1=threading.Thread(target=a)th2=threading.Thread(target=b)th1.start()th2.start()
运行结果:
>>> 第一个函数第二个函数
也有可能是:
>>> 第二个函数第一个函数
为什么会出现这种状况,为什么呢?因为函数a()和函数b()是同时启动的,执行时间差不多,所以有可能是a()先执行完,也有可能是b()先执行完。然后,我们再看看进程的形式th1=threading.Thread(target=a),其中th1是子进程的名字,target锁定函数,如果函数有参数怎么办?要写成threading.Thread(target=a,args=(x,x))这种形式。当把函数写进进程后,就要启动,th1.start()
这段程序不太能体现出线程的优点,我们再写一段程序:
import threading,timedef a(): print('a begin!') print('a is running.........') time.sleep(2) print('a end!')def b(): print('b begin!') print('b is running.........') time.sleep(2) print('b end!')_time=time.time()a()b()print('共耗时%f秒'%(time.time()-_time))
运行结果:
a begin!a is running.........a end!b begin!b is running.........b end!共耗时4.058232秒
上面的代码没有写成进程,所以共耗时4秒。我们把它写成进程:
import threading,timedef a(): print('a begin!') print('a is running.........') time.sleep(2) print('a end!')def b(): print('b begin!') print('b is running.........') time.sleep(2) print('b end!')_time=time.time()_a=threading.Thread(target=a)_b=threading.Thread(target=b)_a.start()_b.start()_b.join()_b.join()print('共耗时%f秒'%(time.time()-_time))
运行结果:
a begin!b begin!a is running.........b is running.........a end!b end!共耗时2.073119秒
从上面的结果可以看出耗时2秒,节省了一半时间。join()函数是起到阻塞的作用,详细用法见我的博客:python多线程中join和setDaemon的用法。
**
线程中的互斥
**
先写个实例程序:
import threading,timenum=0def a(n): global num num=num+n num=num-ndef change(n): for i in range(100000): a(n)t1=threading.Thread(target=change,args=(5,))t2=threading.Thread(target=change,args=(8,))t1.start()t2.start()t1.join()t2.join()print(num)
在上面代码中,执行函数change(),根据我们的算法,无论函数的参数是多少,执行多少次,num的结果应该始终是零。但是运行结果如下:
13
或者:
-2
这是为什么呢?num是全局变量,在同一进程下的线程之间的变量是共享的,所以,在t1和t2这两个进程中都会对num进行操作。当执行到线程t1中num=num+你,应该接着执行t1进程中的num=num-1,但是进程都是同时进行的,所以会对num进行线程t2中的操作,num因此会出现其他值。为了避免多个进程同时对一个变量或者文件操作,python引进了互斥锁:当一个进程对一个变量或一个文件进行操作时,会禁止其他进程对此变量或者文件进行操作。我们可以将上面的代码改写如下:
import threading,timenum=0mylock=threading.Lock()def a(n): global num mylock.acquire() num=num+n num=num-n mylock.release()def change(n): for i in range(100000): a(n)t1=threading.Thread(target=change,args=(5,))t2=threading.Thread(target=change,args=(8,))t1.start()t2.start()t1.join()t2.join()print(num)
这样执行的结果始终是0。此外,只要加锁就一定要解锁,否则会形成死锁,就是其他进程始终不能对变量进行操作。加锁的位置只要能够将变量包住就行,例如将锁加在如下位置也可以:
def change(n): for i in range(100000): mylock.acquire() a(n) mylock.release()
**
python中多线程的本质
**
在python中的多线程其实并不能真正利用多核CPU的优势,这是因为在python中有一个GIL(Global Interpreter Lock)。Python在执行多线程程序时,其中一个线程在执行前先获GIL,这样其他的线程就不能执行。当第一个线程执行了若干行代码后再释放GIL,由另外一个线程获得GIL并执行。由此可见,早Python中多线程必不能有效的利用多核CPU的优势。因此为了个好的有效利用多核CPU,所以我们可以创建多个多线程的进程。
- Python多线程
- Python多线程
- Python多线程
- python多线程
- python 多线程
- python多线程
- python多线程
- python 多线程
- python多线程
- Python多线程
- Python 多线程
- python多线程
- python 多线程
- {python多线程}
- Python 多线程
- Python多线程
- python 多线程
- Python 多线程
- 字符串池和堆
- TOJ 1438.Perfect Pth Powers
- 823oracle
- ReactNative设置 Image容器的 圆角背景
- 【lightoj1294】数学
- python多线程
- 几种硬盘IO性能测试工具
- AndroidCallPhone
- 数据结构实验之排序四:寻找大富翁
- Rocketmq 消息的解压缩
- 数据库相关
- MySQL索引原理及慢查询优化
- 最小的k个数
- DTD