python 线程相关笔记

本文详细解析了线程的概念,包括其与进程的区别、线程的创建与执行,以及线程间的资源共享与同步控制。通过多个实例演示了Python中线程的使用方法,并探讨了全局变量的共享及线程同步的重要性。

线程
概念
线程又被称之为轻量级进程
一个进程可拥有多个并行的线程
通俗的一点说就是一个程序有多个任务可以同时进行
一个进程中线程共享相同的内存单元/内存地址空间,可以访问相同的成员
他们从同一个堆中分配对象,通讯、数据交换,同步操作
由于线程间的通信是在同一地址空间进行的,所以,不需要额外的通讯机制
通过以上等优势来提高Python的速度
进程与线程的区别
进程是系统进行资源分配和调度的独立单位
进程在执行过程中拥有独立的内存单元,多个线程共享,从而提高效率
线程是一个进程的实体,是CPU调度和分配的基本单位,从而提高程序运行效率
线程基本不拥有系统资源,只拥有运行时的一点必不可少的资源,但他与其他线程共享进程中的所有资源
使用多线程程序并发比较高
线程不能独立执行,必须依赖进程
线程执行开销小,但是不利于资源的管理保护
涉及到的模块
from threading import Thread
import time
创建线程
引入模块
import time
from threading import Thread
创建线程
创建一个执行函数
判断是否主动执行
创建单个进程或者循环创建出多个线程
线程开始执行
实例1
from threading import Thread

import time

def xc():
print(“当前线程执行了”)

if name == ‘main’:
for i in range(5):
time.sleep(i)
t = Thread(target=xc)
t.start()

		实例2
			from threading import Thread

import time

def xc(num):
print(“当前线程执行了%d”%num)

if name == ‘main’:
for i in range(5):
time.sleep(i)
t = Thread(target=xc,args=(i+1,))
t.start()

		实例3
			from threading import Thread

import time

def sing():
for i in range(3):
print(“我正在唱歌”)

t = Thread(target=sing)
t.start()

	线程子类化
		将线程封装到一个类中
		对数据进行封装
		实例
			from threading import Thread

import time

class MyThread(Thread):
def run(self):
for i in range(10):
time.sleep(2)
string = "My name is “+self.name+” @ "+str(i)
print(string)

m = MyThread()

m.start()

		实例2
			from threading import Thread

import time

class MyThread(Thread):
def run(self):
for i in range(10):
time.sleep(2)
string = "my name is “+self.name+” @ "+str(i)
print(string)

for i in range(2):
t = MyThread()
t.start()
线程的状态
阻塞 : 多线程的顺序是不规律的,当执行到sleep语句的时候,线程将被阻塞
就绪 : 当sleep语句结束后,程序将要执行,这时线程处在就绪的状态,等待调度,而线程调度会自行选择一个线程执行
运行 : 调度处线程之后,程序执行,这个状态就是运行状态
运行时可能会出现阻塞事件
全局变量
概念
在一个进程内,所有线程共享全局变量
能够在其他地方都不实用的环境中完成线程间的数据共享
缺点 : 线程可以对全局变量随意篡改,可能造成多线程间的全局变量混乱
共享
在线程的操作中,全局变量在线程中是共享的
实例1
from threading import Thread

import time

g_num = 100

def worker1():
global g_num
for i in range(3):
#重新定义了g_num 所以g_num如果不声明为全局变量 他就是局部变量
g_num += 1
print(“worker1里面的g_num等于%d”%g_num)

def worker2():
print(“worker2里面的g_num等于%d”%g_num)

print(“主线程的g_num等于%d”%g_num)

t1 = Thread(target=worker1)
t1.start()

time.sleep(2)
print(’’)

t2 = Thread(target=worker2)
t2.start()

					全局变量共享
				实战2(反例,传参)
					from threading import Thread

import time

g_num = 100

def worker1(num):
for i in range(3):
num += 1
print(“worker1里面的g_num等于%d”%num)

def worker2(num):
print(“worker2里面的g_num等于%d”%num)

print(“主线程的g_num等于%d”%g_num)

t1 = Thread(target=worker1,args=(g_num,))
t1.start()

time.sleep(2)
print(’’)

t2 = Thread(target=worker2,args=(g_num,))
t2.start()

					这个以传参的形式赋值,那么就不属于全局变量,结果不共享
	线程同步
		概念
			当多线程同时修改某一个数据的时候,需要进行同步控制
			线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁
			互斥锁保证每次只有一个线程进行写入操作,从而保证多线程的情况下数据的正确性
			某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改,直到该线程释放资源,将资源的状态变成“非锁定”,其他线程才能再次锁定该资源
			threading模块中定义了Lock类,可以方便的处理锁定
		需要引入的模块
			from  threading   import  Thread
			from  threading  import  Lock
			import  time
		同步控制
			案例
				from threading import Thread

num = 0
def worker():
global num
for i in range(2000000):
num += 1

if name == ‘main’:
for x in range(2):
t = Thread(target=worker)
t.start()

print(“这是线程的结果=======%d”%num)
多次变更,在两万六千次左右就会出现误差
原因
数据进行运算时,先从内存中读到寄存器中去,运算完毕后,再从寄存器中读取到内存中来。
创建锁 : mutex = threading.Lock()
锁定 : mutex.acquire([blocking])
如果设定blocking为True,则当前线程会阻塞,知道获取这个锁为止,如果没有设定,默认为True
如果设定blocking为False,则当前线程不会阻塞
释放 : mutex.release()
实例
from threading import Thread,Lock

import time

num = 0
#创建互斥所
mutex = Lock()
def worker():
global num
for i in range(10000000):
mutexPlag = mutex.acquire(False)
if mutexPlag:
num += 1
mutex.release()

if name == ‘main’:
for i in range(2):
t = Thread(target=worker)
t.start()
t.join()
print(num)

			死锁现象  :  如果将线程锁定,而没有释放,那么就会出现死锁现象
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值