1、程序、进程、线程
程序与进程
程序
- 静态的代码
- 程序运行后至少能创建一个进程
进程
- 执行起来的代码
- 程序的执行实例、动态的
- 进程占用内存资源
- 1个进程至少包含1个线程
进程与线程
进程
- 1个进程至少包含1个线程,即主线程
- 同时也是可以创建多个子线程
- 进程之间的内存空间是独立的,数据是独立的
线程
- 程序执行流的最少单元
- 是CPU的可执行上下文
- 同一个进程中的线程共享同一内存空间,数据共享
- 线程数据的安全性需要保护
多线程
在单个程序中同时运行多个线程完成不同的被划分成一块一块的工作,称为多线程
2、python多线程模块
多线程编程创建方式
第一种 继承Thread
import threading
# 第一种 继承Thread
class MyThred(threading.Thread): # 继承父类
def __init__(self, thread_name):
super(MyThred, self).__init__(name=thread_name) # 调用父类,构造一个自定义构造函数的写法
def run(self):
print("%s 在执行中..." %self.name)
for i in range(10): # 创造10个线程将其运行起来
MyThred("testThread" + str(i)).start()
第二种 (推荐使用)
import threading
def show(num): # 定义一个函数
print('当前线程: %s 在执行...' % num)
for i in range(10):
t = threading.Thread(target=show, args=(i,)) # 定义一个线程,直接实例化Thread这个实例,target执行的目标,args是运行参数,元组只有一个元素加逗号加以区分
t.start()
第三种
import threading
import time
def dowaiting(): # 子线程调用dowaiting让它等一会
print('子线程开始等待...')
time.sleep(3) # 让其等待3秒
print('子线程等待结束')
# 主线程
print('主线程开始执行')
t = threading.Thread(target=dowaiting)
t.start()
print('主线程的其他操作')
t.join() # 让子线程合并到主线程里来,也就是让主线程等待子线程执行结束
print('主线程结束')
3、守护线程
import threading
import time
def dowaiting(): # 子线程调用dowaiting让它等一会
print(threading.current_thread().getName() + '子线程开始等待...') # 可知当前线程是谁
time.sleep(3) # 让其等待3秒
print(threading.current_thread().getName() + '子线程等待结束')
# 主线程
print('主线程开始执行')
for i in range(3): # 创建了3个线程
t = threading.Thread(target=dowaiting)
t.setDaemon(True) # 主线程守护进程
t.start()
print('主线程结束')
4、线程安全
# 线程安全
import threading
import time
number = 0
# 1 : 1000
# 2 : 2000
# 1 : 2120
# 2 : 3456
def add():
global number
for _ in range(1000000):
number += 1
print('子线程 %s 执行结束后:number = %d' % (threading.current_thread().getName(), number))
for i in range(2):
t = threading.Thread(target=add)
t.start()
t.join()
time.sleep(3)
print('主线程结束.number = '+str(number))
5、线程安全与线程锁
- 互斥锁Lock :只能被一个进程所访问
- RLock可重入锁 :可以有多把锁锁在一个对象上
- 信号Semaphore
- 事件Event
- 条件Condition
- Barrier “阻碍”
加互斥锁Lock
import threading
import time
number = 0
lock = threading.Lock() # 定义锁
def add(lk): # 传入锁
global number
# 加锁
lk.acquire()
for _ in range(1000000):
number += 1
print('子线程 %s 执行结束后:number = %d' % (threading.current_thread().getName(), number))
# 解锁
lk.release()
for i in range(2):
t = threading.Thread(target=add, args=(lock, ))
t.start()
time.sleep(3)
print('主线程结束.number = '+str(number))
也可以用with语句加锁,为了防止文件、资源未关闭,锁未释放等问题
import threading
import time
number = 0
lock = threading.Lock() # 定义锁
def add(lk): # 传入锁
global number
# 加锁
with lk:
for _ in range(1000000):
number += 1
print('子线程 %s 执行结束后:number = %d' % (threading.current_thread().getName(), number))
# 解锁
for i in range(2):
t = threading.Thread(target=add, args=(lock, ))
t.start()
time.sleep(3)
print('主线程结束.number = '+str(number))
6、生产者与消费者
多线程的环境配上消息队列,一种模式,解决效率很低的问题。