在python中,多进程是可以利用多核进行真正并行的,但是多线程就不行了,理由可以参考这篇文章python学习笔记- day10-4【问题:为什么python的多线程不能利用多核CPU?】,标题一和标题三都总结得很好。
一,python多线程的基本使用:
import threading, time
def ThreadWorking():
print('thread(%s) start...' % threading.current_thread().name)
print('等待三秒,假装线程在工作')
time.sleep(3)
print('thread(%s) end...' % threading.current_thread().name)
print('main thread(%s) start...' % threading.current_thread().name)
t = threading.Thread(target=ThreadWorking, name="新线程")
t.start()
t.join()
print('main thread(%s) end...' % threading.current_thread().name)
Output:
main thread(MainThread) start...
thread(新线程) start...
等待三秒,假装线程在工作
thread(新线程) end...
main thread(MainThread) end...
用法很简单,不过众所周知的是,多线程难就难在这些线程共享了进程的资源,而这里就需要让多线程修改资源的时候有一定的顺序,就需要同步:下面来看同步
二,同步
同步的实现就是加锁,当一个资源被线程A访问的时候,加上锁,别的线程就访问不了这个资源。等线程A访问完了,就释放这个锁,其他线程就可以去抢这个资源,然后第一个抢到的,重新加上锁。
先看不加锁的话,子线程怎么执行:
import threading, time
def a():
print('thread %s start', threading.current_thread().name)
time.sleep(3)
print('thread %s end', threading.current_thread().name)
def b():
print('thread %s start', threading.current_thread().name)
print('thread %s end', threading.current_thread().name)
pa = threading.Thread(target=a, name="a线程")
pb = threading.Thread(target=b, name='b线程')
print('main thread(%s) start...' % threading.current_thread().name)
pa.start()
pb.start()
pa.join()
pb.join()
print('main thread(%s) end...' % threading.current_thread().name)
Output:
main thread(MainThread) start...
thread %s start a线程
thread %s start b线程
thread %s end b线程
thread %s end a线程
main thread(MainThread) end...
可以看得出来,a,b两个线程在并发抢夺cpu。那么要控制它们的顺序,就要加锁
import threading, time
lock = threading.Lock() #GIL锁,一个进程只有这一个
def a():
lock.acquire() #获取锁
try:
print('thread %s start', threading.current_thread().name)
time.sleep(3)
print('thread %s end', threading.current_thread().name)
finally:
lock.release() #释放锁
def b():
lock.acquire() # 获取锁
try:
print('thread %s start', threading.current_thread().name)
print('thread %s end', threading.current_thread().name)
finally:
lock.release() #释放锁
pa = threading.Thread(target=a, name="a线程")
pb = threading.Thread(target=b, name='b线程')
print('main thread(%s) start...' % threading.current_thread().name)
pa.start()
pb.start()
pa.join()
pb.join()
print('main thread(%s) end...' % threading.current_thread().name)
Output:
main thread(MainThread) start...
thread %s start a线程
thread %s end a线程
thread %s start b线程
thread %s end b线程
main thread(MainThread) end...
加上锁之后,a,b两个线程的顺序就固定下来了,a没有执行完之前,b就获取不到锁,就只能等着。
这里需要注意的是python只能获取GIL锁,然后这个锁是每个进程一个的,不像java那样有对象锁,类锁一类的概念,所以这个GIL锁的存在就是让python多线程无法利用多核的根本原因,详见上面给出的那片文章。