线程梳理

1 threading_lesson

import time
import threading
def music(stype,name):
    print("%s 开始听%s音乐"%(name,stype),time.ctime())
    time.sleep(3)
    print("%s 结束听%s音乐" % (name, stype), time.ctime())
def code(stype,name):
    print("%s 开始敲%s代码"%(name,stype),time.ctime())
    time.sleep(5)
    print("%s 结束敲%s代码" % (name, stype), time.ctime())

if __name__ == "__main__":
    t1=threading.Thread(target=music,args=("rock","alex"))
    """固定格式,target=函数名,args=元组形式的函数实参,实例化一个子线程对象
    """
    t1.start()     #开始执行这个子线程对象
    t2 = threading.Thread(target=code, args=("rock", "alex"))
    t2.start()
    t1.join()       #要在t1实例化的这个线程执行结束之后才能继续执行下面的代码
    t2.join()
    print("ending.....",time.ctime())

2 lesson2-setDaemen

import time
import threading
def music(stype,name):
    print("%s 开始听%s音乐"%(name,stype),time.ctime())
    time.sleep(3)
    print("%s 结束听%s音乐" % (name, stype), time.ctime())
def code(stype,name):
    print("%s 开始敲%s代码"%(name,stype),time.ctime())
    time.sleep(5)
    print("%s 结束敲%s代码" % (name, stype), time.ctime())
if __name__ == "__main__":
    t1=threading.Thread(target=music,args=("rock","alex"))
    t1.setDaemon(True)
    """要在调用start()之前声明,在其他线程执行结束时,无论自己是否执行完毕,立即停止执行
    和t1.join()效果相反。注意后面的参数Ture
    """
    t1.start()
    # t1.run()
    t2 = threading.Thread(target=code, args=("rock", "alex"))
    t2.setDaemon(True)
    # t2.start()
    print("ending.....",time.ctime())

3 线程的继承实例化

import time
import threading
class MyThread(threading.Thread):
    def __init__(self,num):             #不是必须的 ,可以通过这种方式传参
        super().__init__()
        self.num=num
    def run(self) -> None:   #定义每个线程要运行的函数
        print(self.num)
        time.sleep(8)
        print("ok")
if __name__ =="__main__":
    t1=MyThread(1)     #实例化,调用init方法
    t1.setDaemon(True)
    t1.start()         #表示t1对象已经准备好了,执行到这里会调用run()做为任务一部分
    # t1.setDaemon(True)
    # t1.run()            #一般不这样直接用,但也可以调用run(),但是join()和setDaemen变成无效的
    # t2 = MyThread(2)
    # t2.start()
    print("ending....")

4 线程安全问题

"""由于GIL存在而引发的一个问题,首先同一时刻只能有一个线程被cpu执行。在一个进程中可能有多个
线程,共用进程的内存,它们在需要被cpu执行的过程中是竞争关系,又由于用多道技术进行时间轮循实现并发效果
就可能出现线程安全问题
有IO阻塞就立即切换(比如sleep),没有的话就是计算密集型
"""
# import time
# import threading
# num=100
# def mul():
#     global num
#     temp=num
#     # print("t",temp)
#     time.sleep(0.00001)    #这一部分导致结果不固
#     num=temp-1
# l=[]
# for i in range(100):
#     t=threading.Thread(target=mul)
#     t.start()
#     # print(temp)
#     # t.join()
#     l.append(t)
#     # print(t)
# for k in l:
#     k.join()
# print(num)

"""解决方法:在适当地方加互斥锁
"""
import time
import threading
lock=threading.Lock()  #创建线程互斥锁
num=100

def mul():
    global num

    lock.acquire()   #装上互斥锁
    temp=num
    # print("t",temp)
    time.sleep(0.000001)
    temp-=1
    num=temp
    lock.release()   #去掉互斥锁
l=[]
for i in range(100):
    t=threading.Thread(target=mul)
    t.start()
    l.append(t)
    # print(t)
for k in l:
    k.join()
print(num)

5死锁和递归锁

"""前面讲到的线程安全问题可以通过加同步锁的方式来解决
这种锁的实例化方法是lock=threading.Lock(),这种锁只能同时被一个线程使用,并且只能使用一次
如果两个线程都有一把锁,又彼此要对方的锁,则会出现死锁
这个时候要使用递归锁 r_lock=threading.Rlock()
它的内部有一个指针计数器,无线程使用时为0,有线程使用一次为1,这时别的线程不能使用
绑定线程再使用一次,计数器则为2.。。。施放一次计数器减一,为0时回归初始化状态

"""

6同步对象event

"""Event内部包含了一个标志位,初始的时候为false。
可以使用使用set()来将其设置为true;
或者使用clear()将其从新设置为false;
可以使用is_set()来检查标志位的状态;
另一个最重要的函数就是wait(timeout=None),用来阻塞当前线程,
直到event的内部标志位被设置为true或者timeout超时。如果内部标志位为true则wait()函数理解返回。
import threading
event=threading.Event()   #创建同步对象
"""


import threading
import time

class MyThread(threading.Thread):
    def __init__(self, signal):
        threading.Thread.__init__(self)
        self.singal = signal

    def run(self):
        print ("I am %s,I will sleep ..."%self.name)
        self.singal.wait()
        print ("I am %s, I awake..." %self.name)

if __name__ == "__main__":
    singal = threading.Event()
    for t in range(0, 3):
        thread = MyThread(singal)
        thread.start()

    print ("main thread sleep 3 seconds... ")
    time.sleep(3)

    singal.set()

7信号量Semaphore

"""也是一种锁(第三把),锁同时能有几个线程进入cpu,默认为1
"""
import threading
import time
class Mythread(threading.Thread):
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num=num
    def run(self):
        # print("gggg")
        semaphore.acquire()                # if semaphore.acquire():
        print(self.name,self.num)          #     print(self.name,self.num)
        time.sleep(2)                      #     time.sleep(2)
        semaphore.release()                # semaphore.release()

semaphore=threading.Semaphore(5)   #创建信号量,不加参数默认为1
l=[]
if __name__=="__main__":
    for i in range(100):
        t=Mythread(i+1)
        l.append(t)
    for i in l:
        i.start()

8多线程队列

'''
eg:多线程拿出列表(也可以是其他,只是存储数据的一种结构)的最后一个值可能会报错
'''
# import threading
# import time
# l=[2,4,1,5,3]
# def delet():
#     a=l[-1]
#     print(a)
#     time.sleep(2)
#     l.remove(a)
# t1=threading.Thread(target=delet)
# t2=threading.Thread(target=delet,args=())
# t1.start()
# t2.start()
"""两个线程都拿到了列表最后一个5,第一个线程删除之后,第二个线程删除时报错
这种也是一个线程安全问题,主要只有列表这种数据结构引起的
这里到引入多线程队列解决问题
"""
import queue   #导入队列模块
q=queue.Queue(5)
"""#创建一个队列对象,参数5表示这个队列最多能放5个元素,
这种形式下创建的是FIFI(先进先出)类型的队列
还有LIFO(后进先出)q=queue.LifoQueue() 用法相同
还有自定义优先级q=queue.PriorityQueue()  单独有实例
"""
q.put(3,block=True)   #默认block=Ture,等待不报错,改为False发生错误则报错
q.put("alex")
q.put([1,2,5,3])
q.put({"a":222})
q.put((2,31,4))
while True:
    date=q.get(block=True)    #和put默认参数一样
    print(date)

#自定义优先级
# import queue
# q=queue.PriorityQueue(3)
# q.put([2,[1,4,2]])
# q.put([1,{"dd":3}])
# q.put([3,(54,76,)])
# print(q.get())
# print(q.get())
# print(q.get())


9生产者消费者模型

import time
import threading         #线程模块
import queue             #队列模块
q=queue.Queue(10)        #创建一个队列对象,允许放10个数据,不限类型
# print("bug")
def produce_baozi(name):
    for i in range(1,13):
        time.sleep(1)
        print("%s的第%s个包子做好了" % (name,i))
        q.put(i)
        q.task_done()     #线程间通信
def consume_baozi(name):
    for i in range(1, 5):
        q.join()          #如果通信线程没有执行q.task_done(),该线程则会阻塞
        date=q.get()
        time.sleep(1)
        print("%s吃了第%s个包子"%(name,date))
p1=threading.Thread(target=produce_baozi,args=("p1",))
c2=threading.Thread(target=consume_baozi,args=("c2",))
c3=threading.Thread(target=consume_baozi,args=("c3",))
c1=threading.Thread(target=consume_baozi,args=("c1",))
c1.start()
c2.start()
c3.start()
p1.start()
c1.join()
c2.join()
c3.join()
p1.join()
print("end...")

你可能感兴趣的:(python,开发之路)