线程的理解应该结合进程来对比理解更直接
如果我们操作系统当做一个工厂的话,那么创建一个进程就相当于在这个工厂里面新增了一个车间,车间里面存放了很多资源,而车间要运行起来很显然的标志就是流水线,而这些流水线就是线程,可以说线程是执行代码的最小单位。
而线程和进程两者在使用层面上有很大的相似性,所以开启或者说创建线程的2种方式跟创建进程很相似,区别在于导入的模块和类不一样而已。
一、开启线程方法:
第一种:
from threading import Thread
import time
def task(name):
time.sleep(2)
print('%s has no jj' %name)
if __name__ == '__main__':
t=Thread(target=task,args=('JJ',))
t.start()
print('主')
第二种:
from threading import Thread
import time
class MyThread(Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print("%s is running" % self.name)
time.sleep(1)
print("%s is done" % self.name)
t1 = MyThread('Mr hello')
t1.start()
t1.join()
print('zhuzhuzhu')
二、线程之间的数据共享
前面我们学到进程的时候知道进程与进程之间内存空间是相互隔离的,互相无法直接访问到,那么线程之间的共享呢
下面通过一段代码来看看数据直接是否共享:
from threading import Thread
x= 99
def task():
global x
x = 66
t1 = Thread(target=task) # 创建子线程对象
t1.start() # 向操作系统发送子线程执行请求
t1.join() # 子线程完毕后才往下走,此时子进程已经执行了x = 66,如果最终打印
# 的是99,则代表子进程无法修改主进程中的x,如果是66则子进程与主进程公共一内存空间,可以修改
print(x) # 结果为66,证明公用一个内存空间
可以看到,线程之间的数据时具有共享性的,所以就会存在一个隐患,当多个线程同时并发操作同一数据时候或者执行同一代码的时候在某种场景下会导致混乱。
这就是我们后面学到的GIL(global interpreter lock)全局解释器锁的必要性的原因。在这里先提一下。
三、线程的互斥锁:
线程的互斥锁,同理进程的互斥锁,作用也是为了保证数据的安全,何种情况:多线程同时访问操作同一数据时候
先产生锁,再在操作数据的那段代码前后加锁,操作完毕释放锁。实现方法:
from threading import Thread, Lock
import time
import random
import json
mutex = Lock() # 创建锁
class MyThread(Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
time.sleep(0.5) #保证多线程同一时间抢锁,睡个0.5秒,等待大部分线程都能运行到此处,开始抢锁
mutex.acquire() # 加锁
with open('info', 'r', encoding='utf-8') as f1: # 简单模拟抢票过程
dic = json.load(f1)
num = dic.get('remain')
# time.sleep(random.randint(1, 5))
print('剩余票数:%s' % num)
if not num:
print('票已售完,%s购票失败' % self.name)
else:
dic['remain'] -= 1
# time.sleep(random.randint(1, 5))
with open('info', 'w', encoding='utf-8') as f2:
json.dump(dic, f2)
print('用户%s购票成功!' % self.name)
mutex.release() # 释放锁,这里注意释放位置
user2 = MyThread('egon')
user3 = MyThread('jason')
user1 = MyThread('alex')
user2.start()
user3.start()
user1.start()
user1.join()
user2.join()
user3.join()
print('欢迎欢迎')