线程理论和实操
1.什么是线程
进程其实不是一个执行单位. 进程是一个资源单位
每个进程内自带一个线程. 线程才是cpu上的执行单位
如果把操作系统比喻一座工厂
在工厂中每造出一个车间 -> 启动一个进程
每个车间至少有一条流水线 -> 每个进程至少有一个线程
线程 -> 单指代码的执行过程
进程 -> 资源的申请与销毁的过程
2.进程vs线程
1. 内存共享or隔离
多个进程内存空间彼此隔离
同一进程下的多个线程共享该进程内的数据
2. 创造速度
创建线程的速度要远远快与造进程
3.创建线程的两种方式
# -*- encoding:utf-8 -*-
# @time: 2022/8/7 8:44
# @author: Maxs_hu
from threading import Thread
import time
# 方式1:
def task(name):
print('%s is running' % name)
time.sleep(2)
print('done')
if __name__ == '__main__':
t = Thread(target=task, args=('maxs_hu', ))
t.start()
print('主') # 线程创建速度很快.
"""
maxs_hu is running
主
done
"""
# 方式2:
class Mythreading(Thread):
def run(self):
print('%s is running' % self.name)
time.sleep(3)
print('%s is done' % self.name)
if __name__ == '__main__':
t = Mythreading()
t.start()
print('main')
4.线程vs进程代码实现
# -*- encoding:utf-8 -*-
# @time: 2022/8/7 8:53
# @author: Maxs_hu
from threading import Thread
from multiprocessing import Process
# 线程的速度快于进程
def task(name):
print(f'{name} is running')
if __name__ == '__main__':
t = Thread(target=task, args=('子线程', ))
p = Process(target=task, args=('子进程', ))
p.start()
t.start()
print('main')
# 同一进程内的线程共享线程内的资源
x = 100
def task():
global x
x = 1
if __name__ == '__main__':
t = Thread(target=task)
t.start()
t.join() # 等待线程执行完毕
print(x) # x的值被子线程修改
# 查看pid
import os
def task():
print('pid: %s' % os.getpid())
if __name__ == '__main__':
t = Thread(target=task)
t.start()
print('主线程: %s' % os.getpid())
# pid: 5232主线程: 5232
5.守护线程
# -*- encoding:utf-8 -*-
# @time: 2022/8/7 9:09
# @author: Maxs_hu
from threading import Thread, current_thread
import time
# 守护进程会在本进程内的非守护进程的死掉之后跟着死掉
# 守护线程其实守护的是整个进程的运行周期
# def task():
# print('%s is running' % current_thread().name)
# time.sleep(2)
# print('%s is done' % current_thread().name) # 如果主线程在这条之前运行完了. 就不回输出
#
#
# if __name__ == '__main__':
# t = Thread(target=task)
# t.daemon = True # 设置守护线程
# t.start()
# print('main')
# 小案例
def foo():
print(123)
time.sleep(3)
print("end123") # 这个没有输出
def bar():
print(456)
time.sleep(1)
print("end456")
t1 = Thread(target=foo)
t2 = Thread(target=bar)
t1.daemon = True
t1.start()
t2.start()
print("main-------")
"""
123
456
main-------
end456
"""
6.守护线程
# -*- encoding:utf-8 -*-
# @time: 2022/8/7 9:24
# @author: Maxs_hu
# 什么是互斥锁:
# 将多个并发任务对共享数据的修改变成串行, 以保证数据安全
# 加上锁之后效率变低. 保证数据安全
from threading import Thread, Lock
import time
x = 100
# def task():
# global x
# temp = x
# time.sleep(0.1) # 线程全部拿到temp = 100到这里睡了0.1秒. 后面修改数据就都是99. 不符合正常逻辑.
# x = temp - 1
#
#
# if __name__ == '__main__':
# t_ls = []
# for i in range(100):
# t = Thread(target=task)
# t_ls.append(t)
# t.start()
#
# for t in t_ls: # 等待子线程运行完毕
# t.join()
#
# print(x)
mutex = Lock()
def task():
global x
mutex.acquire()
temp = x
time.sleep(0.1) # 线程全部拿到temp = 100到这里睡了0.1秒. 后面修改数据就都是99. 不符合正常逻辑.
x = temp - 1
mutex.release()
if __name__ == '__main__':
t_ls = []
start_time = time.time()
for i in range(100):
t = Thread(target=task)
t_ls.append(t)
t.start()
for t in t_ls: # 等待子线程运行完毕
t.join()
print(x, time.time()-start_time)
7.死锁现象和递归锁
# -*- encoding:utf-8 -*-
# @time: 2022/8/7 10:19
# @author: Maxs_hu
"""
什么是死锁现象:
相当于两个人拿着对方家里的钥匙. 被锁门里面了
互相等着拿对方的锁的现象
怎么解决死锁现象:
递归锁: Rlock原理
给不同的锁赋值obj递归锁对象. 被赋值的锁被acquire多次. 就会在整体标记多次. 只要存在标记. 后面的线程就只能等着
而只有release消除所有的标记次数. 才能开始抢锁. 从而解决死锁现象
递归锁的特点:可以连续的acquire
"""
from threading import Thread, Lock, active_count, RLock
import time
# mutexA=Lock()
# mutexB=Lock()
obj = RLock() # 递归锁的特点:可以连续的acquire
mutexA = obj
mutexB = obj
class Mythread(Thread):
def run(self):
self.f1()
self.f2()
def f1(self):
mutexA.acquire()
print('%s 拿到A锁' % self.name)
mutexB.acquire()
print('%s 拿到B锁' % self.name)
mutexB.release()
mutexA.release()
def f2(self):
mutexB.acquire()
print('%s 拿到B锁' % self.name)
time.sleep(1)
mutexA.acquire()
print('%s 拿到A锁' % self.name)
mutexA.release()
mutexB.release()
if __name__ == '__main__':
for i in range(10):
t = Mythread()
t.start()
# print(active_count())
8.信号量
# -*- encoding:utf-8 -*-
# @time: 2022/8/7 10:44
# @author: Maxs_hu
# 信号量: 同一时刻并发执行的任务数
import time
import random
from threading import Thread, current_thread, Semaphore
mutex = Semaphore(5) # 设置同时并发量为5
def task():
with mutex:
print('%s 在上厕所' % current_thread().name)
time.sleep(random.randint(1, 3))
if __name__ == '__main__':
for i in range(20):
t = Thread(target=task)
t.start()
本文来自博客园,作者:{Max},仅供学习和参考
posted on 2022-08-07 11:02 huxiaofeng 阅读(155) 评论(0) 编辑 收藏 举报