多线程

基本概念:
  线程:线程是进程中的每个子任务,不能独立存在
  进程:独立的所有子任务的集合
  线程、进程:目的都是想同时完成任务


进程的特点:独立(内存独立,CPU使用独立)启动进程开销大(速率低),进程之间很难共享数据,和数据通信,数据安全高。


线程的特点:依赖进程(内存共享,cup独立使用),线程之间共享数据容易,方便通信,线程不安全

线程又可以分为:

内核线程:由操作系统内核创建和撤销

用户线程:不需要内核支持而在用户程序中实现的线程

线程常用的两个模块:_thread和threading

Threading 模块除了包括_thread模块中的所有方法外,还提供了其它方法:

threading.currentThread():返回当前的线程变量

threading.enumerate():返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。

threading.activeCount():返回正在运行的线程数量,与len(threading.currentThread())有相同的结果

 

除了使用方法外,线程模块同样提供了Thread类来处理线程,

Thread类提供了以下方法:

run():用以表示线程活动的方法

start():启动线程活动

join([time]):等待至线程终止。这阻塞调用线程直至线程的jion()方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。

isAlive():返回线程是否是活动的。

getName():返回线程名

setName():设置线程名


python 线程有两种方式:函数方式和类方式:

函数式:

在python3中thread模块以被弃用,为了兼容,在python3中重命名为‘_thread’,threading模块包括了_thread模块的全部功能。

定义新线程: threading.start_thread(function,args[, kwargs])

      单线程列子:

import _thread
import threading
import time
def test():
    for i in range(1,10):
        print(i)
        time.sleep(1)
print('------main-------')
# 启动线程
threading._start_new_thread(test,())
# 不结束线程
input()
导入模块,定义一个函数,然后定义一个线程,将test函数传入,然后test函数就变成了一个线程,input的作用是等待用户输入,让程序不结束。
多线程例子:
import _thread
import threading
import time
def test():
    for i in range(1,10):
        print(i)
        time.sleep(1)
print('------main-------')
# 启动线程
threading._start_new_thread(test,())
for i in range(50,39,-1):
    print(i)
    time.sleep(1)
# 不结束线程
input()
多线程和单线程差不多,单线程只是运行一个线程,多线程是运行多个线程,这里可以不用定义两个线程,只要将一个for语句写在定义新线程前面即可,这也算一个线程。
多线程运行的规则:假设有两个线程A和B,多线程运行就是先执行一段A,再执行一段B,这样做的好处可以节省资源和时间。
类方式:
 单线程:
import _thread
import threading
import time
class mythread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        print('mythread')
    def run(self):
        for i in range(11):
            print(i)
            time.sleep(1)
t=mythread()
t.start()
类方式创建类时要继承threading.Thread这个类,这个类里面有很多方法,其中就有start和run方法,父类也有start方法,我们可以自己不用定义,start方法会自动调用run方法,父类里面也有run方法,我们这里要重写父类的方法。
多线程:
import _thread
import threading
import time
class mythread(threading.Thread):
    def __init__(self,name):
        threading.Thread.__init__(self)
        self.name=name
        print('mythread')
    def run(self):
        for i in range(11):
            print('%s\t%d'%(self.name,i))
            time.sleep(1)
M1=mythread('mythread_1')
M2=mythread('mythread_2')
# 线程名字
# t.getName()
# print(t)
# 继承了父类的start方法,会自动调用run()方法,可以重写,但会失去其中的意义
M1.start()
M2.start()
for j in range(50,39,-1):
    print(j)
    time.sleep(1)
这里多线程就要定义两个对象,这就是两个线程,启用后输出的结果是M1和M2分别输出一个数,直至输完。
死锁:

什么是死锁

在编写多线程的时候,必须要注意资源的使用问题,如果两个或多个线程分别拥有不同的资源,而又同时需要对方释放资源才能运行,就会发生死锁

简单来说:死锁就是当一个或多个进程都在等待系统资源,而资源本身又被占用时,所产生的一种状态。

 

造成死锁的原因:多线程竞争共享资源。由于资源被占用,资源不足或进程推进顺序不当等原因造成线程处于永久阻塞状态,从而引发死锁。

这个时候我们就引进了线程锁:

列:

import _thread
import threading
import time
class mythread(threading.Thread):
    def run(self):
        for i in range(1,11):
            # 关锁
            cond.acquire()
            print(i)
            # 开锁
            cond.release()
lock=threading.Lock()
cond=threading.Condition(lock=lock)
M1=mythread()
M2=mythread()
M1.start()
M2.start()
结果是M1先输出,M2后输出,这就相当于单线程,一个线程先运行完毕后再运行下一个线程,但线程锁不止这点,它可以根据要求来进行锁,比如M1输出到6的时候就锁住,然后运行M2,M2运行完毕后再运行M1。

锁定是单线程运行

线程的状态:

1.    新建状态(New):新创建了一个线程对象

2.    就绪状态(Runnable):线程对象创建后,其它线程调用了该对象的start方法,可运行线程池中,变得可运行,等待获取CPU的使用权

3.    运行状态(Running):就绪状态的线程获取了CPU,暂时停止运行执行程序代码。

4.    阻塞状态(Blocked):阻塞状态是线程因为某些原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞分三种:

1.    等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中

2.    同步阻塞:运行的线程在获取对象的同步锁时若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

3.    其它阻塞:运行的线程执行sleep()或join方法,或者发出了I/O时,JVM会把该线程置  阻塞状态。当sleep()状态超时时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态

5.死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命

由于并发的问题,需要加锁:

锁当然有锁定和未锁定两种状态,当一个线程要访问共享数据时,必须要先获得锁定,如果已经有别的线程获得锁,那么就进入暂定状态,等别的线程把锁释放后,再进行操作。

 

Condition:更精确的控制锁,提供了四个方法,上锁(acquire()),

等待(wait()),解锁(release()),唤醒(notify(),notify_all())

lock=threading.lock()

threading.Condition(lock=lock)


 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值