Python中的多进程与多线程(三)
Python实现多线程
一、背景了解
-
多任务可以由多进程完成,也可以由一个进程内的多线程完成。在前面的博客中有提到,进程是由若干线程组成的,一个进程至少含有一个线程。
-
多线程类似于同时执行多个不同程序,多线程运行有以下优点:
-
使用线程可以把占据长时间的任务放到后台去处理
-
程序的运行速度可能会加快
-
在一些等待的任务实现上比如用户输入、文件读写和网络数据收发等,线程就比较有用。在这种情况下通过多线程可以释放一些珍贵的资源如内存占用等
-
用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
-
-
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
-
每个线程都有它自己的一组CPU寄存器,称为线程的上下文,指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器
-
线程可以分为:
-
内核线程:由操作系统内核创建和撤销
-
用户线程:不需要内核支持而在用户程序中实现的线程
-
-
线程具有以下特点:
-
线程可以被抢占(中断)
-
在其它线程运行时,线程可以暂时搁置(也称为睡眠)(线程的退让)
-
二、Python多线程编程
1、threading
-
Python标准库中提供了threading模块,对多线程编程提供了很大的支持
-
下面使用threading模块实现多线程:
import time, threading
def test(index):
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
print("Thread %s starts..." % threading.current_thread().name)
print("Index : %s..." % index)
time.sleep(3)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
print("Thread %s ends..." % threading.current_thread().name)
if __name__ == "__main__":
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
print("Thread %s starts..." % threading.current_thread().name)
#创建线程
th = threading.Thread(target=test, args=(1, ), name="test_thread")
time.sleep(2)
#启动线程
#等待线程执行结束
th.join()
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
print("Thread %s ends..." % threading.current_thread().name)
- 运行结果:
2018-09-30 21:33:58
Thread MainThread starts...
2018-09-30 21:34:00
Thread test_thread starts...
Index : 1...
2018-09-30 21:34:03
Thread test_thread ends...
2018-09-30 21:34:03
Thread MainThread ends...
2、Lock
-
多进程与多线程的最大不同在于,多进程中,同一个变量,各自有一份拷贝存放于每个进程中,互不影响。而多线程中,所有变量都由所有线程共享,所以,任何一个共享变量都可以被任何一个线程修改。因此线程之间共享数据最大的危险在于多个线程同时改变一个变量。为了解决这个问题,我们可以借助于threading模块的Lock类来给共享变量加锁
-
下面给出使用Lock对共享变量进行加锁的示例:
import threading
class Account:
def __init__(self):
self.balance = 0
def add(self, lock):
#获得锁
lock.acquire()
for i in range(0,100000):
self.balance += 1
#释放锁
lock.release()
def delete(self, lock):
lock.acquire()
for i in range(0,100000):
self.balance -=1
lock.release()
if __name__ == "__main__":
account = Account()
lock = threading.Lock()
#创建线程
thread_add = threading.Thread(target=account.add, args=(lock, ), name='Add')
thread_del = threading.Thread(target=account.delete, args=(lock, ), name='Delete')
#启动线程
thread_add.start()
thread_del.start()
#等待线程结束
thread_add.join()
thread_del.join()
print(account.balance)