Python多线程threading

进程与线程的区别:

进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。

线程:是进程的一个执行单元,任务调度和执行的基本单位。

区别

  • 在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
  • 所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行。(通过CPU调度,在每个时间片中只有一个线程执行)
  • 内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
  • 包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

P y t h o n Python Python中的多线程:

python中多线程的使用有两种方式:

  • 函数
  • 类包装线程对象

1.函数:
调用threading模块中的
threading.Thread函数来产生新线程。

threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

参数:

  • g r o u p group group
    线程组,默认为None,为以后拓展ThreadGroup类实现而保留。
  • t a r g e t target target
    用于run()方法调用的可调用对象。默认是None,表示不需要调用任何方法。
  • n a m e name name
    线程名称,默认情况下由"Thread-N"构成,其中N为十进制数
  • a r g s args args
    调用目标函数的参数元组
  • k w a r g s kwargs kwargs
    调用目标函数的关键字参数字典
def fun():
	...
	
t1 = threading.Thread(target=fun,name="t1")
t1.start()

2.继承threading.Thread来自定义线程类,本质是重构Thread类中的run方法。(推荐)

class MyThread(threading.Thread):
	def __init__(self,n):
		super(MyThread,self).__init__()
		self.n=n
	def fun(self):
		...
t1 = MyThread("t1")
t1.start()

t r e a d i n g . T h r e a d treading.Thread treading.Thread对象的一些常用方法:

  1. r u n ( ) run() run()
    用以表示线程活动的方法
  2. s t a r t ( ) start() start()
    启动线程活动
  3. j o i n ( [ t i m e ] ) join([time]) join([time])
    等待至线程中止。例如主线程A中,创建了子线程B,并且在主线程A中调用了B.join(),那么,主线程A会在调用的地方等待,直到子线程B完成操作后,才可以接着往下执行,那么在调用这个线程时可以使用被调用线程的join方法。join([timeout]) 里面的参数时可选的,代表线程运行的最大时间,即如果超过这个时间,不管这个此线程有没有执行完毕都会被回收,然后主线程或函数都会接着执行的,如果线程执行时间小于参数表示的时间,则接着执行,不用一定要等待到参数表示的时间。
  4. i s A l i v e ( ) isAlive() isAlive()
    返回线程是否活动
  5. g e t N a m e ( ) getName() getName()
    返回线程名
  6. s e t N a m e ( ) setName() setName()
    设置线程名
  7. s e t D e a m o n ( ) setDeamon() setDeamon()
    主线程A中,创建了子线程B,并且在主线程A中调用了B.setDaemon(True),这个的意思是,把主线程A设置为守护线程,这时候,要是主线程A执行结束了,就不管子线程B是否完成,一并和主线程A退出。这就是setDaemon方法的含义,这基本和join是相反的。此外,还有个要特别注意的:必须在start() 方法调用之前设置,如果不设置为守护线程,程序会被无限挂起,只有等待了所有线程结束它才结束。

threading类的重要函数:

  1. a c t i v e c o u n t ( ) active_count() activecount()
    返回当前存活的线程类 Thread 对象。
  2. c u r r e n t t h r e a d ( ) current_thread() currentthread()
    返回当前对应调用者的控制线程的 Thread 对象。
  3. g e t i d e n t ( ) get_ident() getident()
    返回当前线程的 “线程标识符”。它是一个非零的整数。
  4. e n u m e r a t e ( ) enumerate() enumerate()
    以列表形式返回当前所有存活的 Thread 对象。
  5. m a i n t h r e a d ( ) main_thread() mainthread()
    返回主 Thread 对象。一般情况下,主线程是Python解释器开始时创建的线程。
  6. s t a c k s i z e ( [ s i z e ] ) stack_size([size]) stacksize([size])
    返回创建线程时用的堆栈大小。

1.原始锁(互斥锁)
t h r e a d i n g . L o c k threading.Lock threading.Lock
实现原始锁对象的类。一旦一个线程获得一个锁,会阻塞随后尝试获得此锁的线程,直到它被释放;但任何线程都可以释放它。

lock=threading.Lock() #锁对象
lock.acquire() #关锁
lock.release() #开锁
# acquire和release一般写在run函数里,例如:
# lock.acquire()
# change something...
# lock.release()

2.递归锁(RLock)
互斥锁锁住之后,不管是此线程还是其他线程都不可以再用此锁,而递归锁锁住之后,此进程还可以继续acquire,但其他进程不可以。即此锁支持同一线程中多次请求同一资源。需要注意的是,acquire和release必须成对出现。

缺点:锁住的代码只能以单线程执行;由于可以存在多个锁,不同的线程可以持有不同的锁,试图获得对方持有的锁时,可能会造成死锁。

3.高级锁(threading.Condition())
可以使一个或多个进程等待知道其他线程调度或通知。

wait
该方法用来将当前线程置入休眠状态,直到接到通知或被中断为止。在调用 wait()之前,线程必须要获得该对象的对象监视器锁,即只能在同步方法或同步块中调用 wait()方法。调用wait()方法之后,当前线程会释放锁,直至该线程被Notify()、NotifyAll()或者超时线程又重新获得Lock。

notify(n=1):通知其他线程,那些挂起的线程接到这个通知之后会开始运行,
默认是通知一个正等待该condition的线程,最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才能调用,
否则会触发RuntimeError。notify()不会主动释放Lock。

notifyAll(): 如果wait状态线程比较多,notifyAll的作用就是通知所有线程(这个一般用得少)
lock_con=threading.Condition([Lock/Rlock]): 锁是可选选项,
默认创建一个RLock(),一般都用默认。

import threading,time
from random import randint
class Producer(threading.Thread):
    def run(self):
        global L
        while True:
            val=randint(0,100)
            # print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
            print('生产者',self.name,' Append'+str(val),L)
            if lock_con.acquire():
                L.append(val)
                lock_con.notify()
                lock_con.release()
            time.sleep(3)
class Consumer(threading.Thread):
    def run(self):
        global L
        while True:
            lock_con.acquire()
            if len(L)==0:
                lock_con.wait()
            print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
            print('消费者',self.name,'Delete'+str(L[0]),L)
            del L[0]
            lock_con.release()
            time.sleep(0.5)
if __name__=='__main__':
    L=[]
    lock_con=threading.Condition()
    threads=[]
    for i in range(5):
        threads.append(Producer())
    threads.append(Consumer())
    for t in threads:
        t.start()
    for t in threads:
        t.join()
### 回答1: Python多线程是通过threading模块来实现的。它允许程序在同一时间内执行多个线程,从而提高程序的效率。使用多线程可以让程序在执行耗时操作时不会阻塞主线程,从而提高程序的响应速度。在Python中,使用threading模块创建线程非常简单,只需要继承Thread类并实现run方法即可。同时,Python还提供了一些线程同步的机制,如锁、信号量、条件变量等,可以保证多个线程之间的数据同步和互斥访问。 ### 回答2: Python 是一种非常常用的编程语言,它的一个主要特点是它可以方便快捷地处理并行任务。Python 中处理并行任务的机制有很多,其中最常用的机制是多线程 threading多线程是指在一个程序中同时运行多个线程,这些线程可以共享一些系统资源,如 CPU 和内存。这样做的好处是可以使程序运行更加高效,快速地响应用户的操作。多线程因其高效、灵活、易于实现等特点,在多种应用场景中得到了广泛应用。 Python 中的 threading 模块是用于实现基本多线程功能的标准库之一。使用 threading 模块可以轻松创建和管理多个线程。可以使用 threading.Thread() 函数实例化一个线程对象和它相应的线程函数,然后通过调用 start() 方法启动该线程。在 start() 方法被调用之后,线程就开始了运行,并可以执行与其他线程并行运行的一些任务。当线程运行完所需任务之后,可以使用 join() 方法阻塞主线程,以等待该线程的结束。 使用 threading 模块,还可以使用锁(lock)机制来控制多个线程对于共享资源的访问。锁机制允许线程互斥地访问共享资源,以避免线程之间的竞争和冲突。如果有多个线程都希望使用同一个共享资源,可以使用 threading.Lock() 函数创建一个锁对象,然后使用 acquire() 方法获取锁,使用 release() 方法释放锁。 需要注意的是,虽然多线程可以提高程序运行的效率,但不当地使用多线程也可能会导致程序出现并发问题,如死锁等。因此,在使用多线程时,应谨慎地考虑各个线程对于共享资源的访问顺序和方式,以确保程序的安全和正确性。 总之,Python 中的多线程 threading 机制是非常强大和灵活的。通过它我们可以轻松地实现并行处理的功能,提高程序的效率和性能。但在使用多线程时,需要注意确保程序的安全和正确性,避免出现并发问题。 ### 回答3: Python多线程模块threadingPython中实现多线程的解决方案之一。threading模块提供了一个Thread类作为多线程的基础,可以通过派生Thread子类和重写它的run()方法来定义线程的行为。 Python多线程实现为“线程全局解释器锁(Global Interpreter Lock,GIL)”模型,即同一进程中多个线程共享一个解释器,而只有一个线程可以执行Python代码(线程安全的C扩展模块除外)。这意味着,Python多线程无法实现真正的并行执行,只能通过多个线程之间的切换来实现并发。 使用Python多线程可以带来以下优点: 1. 提高程序响应速度:可以让程序在等待I/O的同时继续执行其他任务,提高了程序的并发处理能力。 2. 更好地利用多核CPU:虽然Python多线程不能实现真正的并行执行,但可以在多核CPU上将任务分配到不同的核上执行,从而更好地利用CPU资源。 3. 代码可读性高:Python多线程的实现相对简单,代码易读易懂。 然而,在使用Python多线程的过程中,也需要注意以下问题: 1. 线程同步问题:由于多个线程可能同时访问共享的数据,因此需要使用锁、信号量等线程同步机制来避免线程冲突。 2. 可能会出现死锁和饥饿问题:死锁是指多个线程相互等待对方释放资源而无法继续执行,饥饿是指某个线程因调度算法等原因无法获得执行机会。这些问题需要仔细设计线程的互动方式来避免。 3. Python多线程无法利用CPU的多核处理能力:Python的GIL模型限制了同一时刻只有一个线程能执行Python代码,因此无法利用多核CPU实现真正的并行处理。 总之,Python多线程是一种方便实用的线程处理方式,可以有效提高程序的并发处理能力,但也需要注意线程同步等问题,对于高性能的性能要求,建议使用Python中的进程池等多进程方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值