Python的多线程,守护线程,线程安全_python多线程安全

# print(lst)
for i in lst:
    i.join()
endtime = time.time()
print("运行的时间是{}".format(endtime - startime) ) # 运行的时间是1.8805944919586182

#多进程速度

if name == “__main__”:
lst = []
startime = time.time()
for i in range(10000):
p = Process(target=func,args=(i,))
p.start()
lst.append§
# print(lst)
for i in lst:
i.join()
endtime = time.time()
print(“运行的时间是{}”.format(endtime - startime) ) # 运行的时间是101.68004035949707


多进程:1000个进程耗时9.06秒  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/8db24f608da644fcb4316a8e502a5daa.png)


多线程:多线程之间,数据共享,可以直接操作数据。1000个线程耗时0.087秒,差距巨大,所以对于IO密集型,还是用多线程较快  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/fbcd8d9305a24115b9ff034df176b707.png)


多进程执行计算密集型,如果各个进程间各计算各的,不用共享数据,由于可以使用多核,比多线程快。  
 如果是各个进程间数据共享,同步计算最终结果,多进程反而非常慢,远远慢于多线程


#(3) 多线程之间,数据共享



num = 100
lst = []
def func():
global num
num -= 1

for i in range(100):
t = Thread(target=func)
t.start()
lst.append(t)

for i in lst:
i.join()

print(num)


多线程之间共享数据,可以直接操作  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9c8584e5116346debc7254d4a8d022f6.png)


## 2、自定义线程类


#用类定义线程,必须手动调用父类\_\_init\_\_方法,必须重载父类run方法,定义自己线程类逻辑  
 from threading import Thread  
 import os,time


### (1)必须继承父类Thread,来自定义线程类



class MyThread(Thread):

def \_\_init\_\_(self,name):
    # 手动调用父类的构造方法
    super().__init__()
    # 自定义当前类需要传递的参数
    self.name = name

def run(self):
    print(  "当前进程号{},name={}".format(os.getpid() , self.name)  )

if name == “__main__”:
t = MyThread(“我是线程”)
t.start()
print( “当前进程号{}”.format(os.getpid()) )


新版:  
 #自定义线程类



from threading import Thread,current_thread

(1)必须继承父类Thread,来自定义线程类

class MyThread(Thread):
def __init__(self,name):
# 手动调用父类的构造方法
super().init()
# 自定义当前类需要传递的参数
self.name = name

def run(self):
    print(f"当前线程的线程号是{current\_thread().ident}")

if name == ‘__main__’:
for i in range(10):
t = MyThread(f"线程{i}")
t.start()


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/aa250878ae74446db4ba69113ca78ac8.png)


### (2)线程中的相关属性



线程.is_alive() 检测线程是否仍然存在

线程.setName() 设置线程名字

线程.getName() 获取线程名字

1.currentThread().ident 查看线程id号 新版用current_thread().ident

2.enumerate() 返回目前正在运行的线程列表

3.activeCount() 返回目前正在运行的线程数量


getName,setName被弃用了  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c36081fcd4c6402a8863b8ae58537dca.png)


新版:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/f087bfcb38604e6fb066595b173211ba.png)



def func():
time.sleep(1)
if name == “__main__”:
t = Thread(target=func)
t.start()
# 检测线程是否仍然存在
print( t.is_alive() )
# 线程.getName() 获取线程名字
print(t.getName())
# 设置线程名字
t.setName(“抓API接口”)
print(t.getName())

from threading import currentThread
from threading import enumerate
from threading import activeCount
def func():
time.sleep(0.1)
print(“当前子线程号id是{},进程号{}”.format( currentThread().ident ,os.getpid()) )

if name == “__main__”:
t = Thread(target=func)
t.start()
print(“当前主线程号id是{},进程号{}”.format( currentThread().ident ,os.getpid()) )

for i in range(5):
    t = Thread(target=func)
    t.start()
# 返回目前正在运行的线程列表
lst = enumerate()
print(lst,len(lst))
# 返回目前正在运行的线程数量 (了解)
print(activeCount())

新版:



### 线程中的相关属性

import time
from threading import Thread,current_thread
from threading import enumerate
from threading import active_count

def func():
time.sleep(1)
print(f"当前子线程的线程号{current_thread().ident}")

if name == ‘__main__’:
for i in range(5):
t = Thread(target=func)
t.start()
#设置线程名
t.name = f"抓API接口{i}"

# 返回目前正在运行的线程列表
lst = enumerate()
print(lst,len(lst))
# 返回目前正在运行的线程数量 (了解)
print(active_count())

当前运行线程数量,一个主线程,5个子线程  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/8b5a281e31af41b0a33393f0b6ad32ce.png)


## 3、守护线程


等待所有线程全部执行完毕之后,自己再终止程序,守护所有线程



from threading import Thread
import time
def func1():
while True:
time.sleep(1)
print(“我是函数func1”)

def func2():
print("我是func2 start … ")
time.sleep(3)
print("我是func2 end … ")

def func3():
print("我是func3 start … ")
time.sleep(6)
print("我是func3 end … ")

if name == “__main__”:
t = Thread(target=func1)
t2 = Thread(target=func2)
t3 = Thread(target=func3)

# 设置守护线程 (启动前设置) 新版本该方法已弃用
t.setDaemon(True)

t.start()
t2.start()
t3.start()

print("主线程执行结束.... ")

新版本设置守护线程的setDaemon()方法已弃用,改为了通过属性设置  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/19f1cdcfd3464d8caf177f48590d4cee.png)


守护线程是等所有线程执行结束,自己再终止程序,守护所有线程  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7233f9d97f30429b9bd423eb93a28330.png)


## 4、线程中的数据安全问题


#多线程之间共享全局变量,出现数据错误问题



import threading

#全局变量
g_sum = 0

def sum1():
for i in range(1000000):
# 不可变类型用方法修改数据,要声明为全局变量
global g_sum
g_sum += 1
print(‘sum1’, g_sum)

def sum2():
for i in range(1000000):
global g_sum
g_sum += 1
print(‘sum2’, g_sum)

if name == ‘__main__’:
sum1_thread = threading.Thread(target=sum1)
sum2_thread = threading.Thread(target=sum2)
sum1_thread.start()
sum2_thread.start()


sum1 911662  
 sum2 1434503


出现的结果不是2百万,由于两个线程是随机执行的,有可能几乎同时对数据进行操作,导致少加的问题  
 解决办法:上锁  
 互斥锁:


互斥锁:对共享数据进行锁定,保证同一时刻只能有一个线程去操作  
 注意:  
 互斥锁是多个线程一起去抢,抢到锁的线程先执行,没抢到锁的线程需要等待,等互斥锁使用完释放后,  
 其他等待的线程再去抢这个锁


线程不安全,执行结果不对  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/adbffbe1f8de4170b32ff099c4433d01.png)


多个线程可能同时操作数据,拿到的数据一样,操作后的结果不一样。造成混乱。比如几乎同时拿到1,运算需要时间,但不同线程读取得到的数据是一样的。  
 线程1拿到数据加1,得到2,线程2拿到数据减1,得到0  
 线程1往原来数据存2,线程2往原来存0,以后面放的为准,下次操作又会出现同样的混乱。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/91a6b21eb6534a9e81e740b76af9c019.png)


上锁:不同的线程采用同步计算,当一个线程运算完,才释放锁,让另一个线程运算



from threading import Thread , Lock
import time

n = 0

def func1(lock):
global n

lock.acquire() 
for i in range(1000000):        
    n += 1
lock.release()

def func2(lock):
global n
# with语法可以简化上锁+解锁的操作,自动完成
with lock:
for i in range(1000000):
n -= 1

if name == “__main__”:
lst = []
lock = Lock()

start = time.time()
for i in range(10):

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注网络安全获取)
img

写在最后

在结束之际,我想重申的是,学习并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。

需要完整版PDF学习资源私我

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。**

需要完整版PDF学习资源私我

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-byE3pdIL-1712857106319)]

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 很抱歉,我之前回答的还是这个问题。以下是一个稍微复杂一点的 Python 多线程实例,可以用来计算一个矩阵的乘积: ```python import threading import numpy as np # 定义矩阵的大小 MATRIX_SIZE = 1000 # 初始化两个随机矩阵 matrix_a = np.random.rand(MATRIX_SIZE, MATRIX_SIZE) matrix_b = np.random.rand(MATRIX_SIZE, MATRIX_SIZE) # 初始化结果矩阵 result_matrix = np.zeros((MATRIX_SIZE, MATRIX_SIZE)) # 定义一个函数,用来计算矩阵的乘积 def multiply(start, end): for i in range(start, end): for j in range(MATRIX_SIZE): for k in range(MATRIX_SIZE): result_matrix[i][j] += matrix_a[i][k] * matrix_b[k][j] # 定义线程数量 NUM_THREADS = 4 # 计算每个线程需要计算的行数 rows_per_thread = MATRIX_SIZE // NUM_THREADS # 创建线程列表 threads = [] # 启动线程 for i in range(NUM_THREADS): start = i * rows_per_thread end = (i + 1) * rows_per_thread t = threading.Thread(target=multiply, args=(start, end)) threads.append(t) t.start() # 等待所有线程结束 for t in threads: t.join() # 检查结果是否正确 expected_result = np.dot(matrix_a, matrix_b) assert np.array_equal(result_matrix, expected_result) # 输出 Done 表示程序执行完毕 print("Done") ``` 这个例子首先初始化两个随机矩阵,然后定义一个函数 multiply,用来计算这两个矩阵的乘积。然后,它将矩阵分成若干个部分,每个部分分配给一个线程来计算。最后,它等待所有线程结束,检查结果是否正确,并输出 Done 表示程序执行完毕。 希望这个例子能够帮助您更好地理解 Python 多线程的使用方法。 ### 回答2: Python多线程实例是指在Python编程语言中使用多线程进行并发编程的实例。在Python中,可以使用内置的threading模块来创建和管理多线程。 通过创建多线程,可以在程序中同时执行多个任务。这对于需要同时处理多个任务的情况非常有用。例如,在下载大文件时,可以使用多线程同时下载多个文件,加快下载速度。此外,多线程还可以用于处理网络请求、图像处理、数据处理等耗时操作,提高程序的运行效率。 使用Python多线程的主要步骤如下: 1. 导入threading模块。 ``` import threading ``` 2. 创建一个线程对象,可以通过继承threading.Thread类或使用threading.Thread()函数创建。 ``` class MyThread(threading.Thread): def __init__(self, name): super().__init__() self.name = name def run(self): # 线程执行的代码 print("Hello, " + self.name) thread1 = MyThread("Thread 1") thread2 = threading.Thread(target=func, args=("Thread 2",)) ``` 3. 启动线程。 ``` thread1.start() thread2.start() ``` 4. 等待线程结束。 ``` thread1.join() thread2.join() ``` 以上代码演示了两种创建多线程的方法:1)继承threading.Thread类,重写run方法;2)使用函数作为线程的执行内容。线程的启动调用start()方法,等待线程结束使用join()方法。 需要注意的是,Python多线程的并发程度受到全局解释器锁(GIL)的限制,因此对于计算密集型的任务,多线程并不能发挥出多核的优势。如果需要发挥多核性能,可以考虑使用多进程编程。 总之,Python多线程实例能够提高程序的并发处理能力,适用于需要同时处理多个任务的场景。通过合理设计线程的数量和任务分配,可以提高程序的性能和效率。 ### 回答3: Python多线程实例是指通过使用多线程的技术来提高Python程序的运行效率和性能。在Python中,我们可以使用threading模块来实现多线程多线程技术可以同时执行多个任务,提高程序的运行速度。在Python中,我们可以通过创建Thread对象并调用start()方法来启动一个线程。下面是一个简单的例子: import threading def print_numbers(): for i in range(1, 11): print(i) def print_letters(): for letter in ['A', 'B', 'C', 'D', 'E']: print(letter) # 创建两个线程 t1 = threading.Thread(target=print_numbers) t2 = threading.Thread(target=print_letters) # 启动两个线程 t1.start() t2.start() # 等待两个线程结束 t1.join() t2.join() # 主线程继续执行 print("主线程结束") 以上代码中,我们创建了两个线程,分别执行print_numbers()和print_letters()函数。通过调用start()方法启动线程,并通过join()方法等待两个线程执行完毕。最后,主线程继续执行并打印出一段文字。 需要注意的是,多线程并不一定能提高程序的运行速度,因为在Python中,全局解释器锁(Global Interpreter Lock,GIL)会限制同一时间只能有一个线程执行Python字节码。因此,在CPU密集型任务中,多线程并不能真正实现并行计算。但是,在IO密集型任务中,多线程能够提高程序的运行效率。 总结起来,Python多线程实例可以通过使用threading模块来实现。多线程能够提高IO密集型任务的运行效率,但在CPU密集型任务中并不能真正实现并行计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值