Python线程

2021-07-16 01:08

阅读:394

标签:串行   tpi   bre   cti   isa   while   为什么   字节码   打开   

#
# [<_mainthread started>, ]
# 2
# 主进程/主线程
# Thread-1



#  join 方法


# from threading import Thread
# import time
# def func():
#     time.sleep(2)
#     print(‘睡觉‘)
#
# if __name__ == ‘__main__‘:
#     t = Thread(target=func)
#     t.start()
#     t.join()  #  等待子线程先执行,子线程结束后执行主进程
#     print("主线程")
#     print(t.is_alive())

#  结果:
# 睡觉
# 主线程
# False


# 守护线程
# 无论是进程还是线程,都遵循:守护xx会等待主xx运行完毕后被销毁.需要强调的是:运行完毕并非终止运行
# 1.对主进程来说,运行完毕指的是主进程代码运行完毕
# 2.对主线程来说,运行完毕指的是主线程内所有的进程内所有非守护全部运行完毕,主进程才算运行完毕

# 具体解释:
    # 1.主进程在其代码结束后就已经算运行完毕(守护进程在此时就被回收),然后主进程会一直非守护的子进程都
#运行完毕后回收子进程的资源(否者会产生僵死进程),才会结束.
    # 2.主线程在其它非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收).因为主线程
    #的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束

# from threading import Thread
# import time
# def func1():
#     time.sleep(3)
#     print("睡觉")
# def func2():
#     time.sleep(2)
#     print("吃饭")
# if __name__ == ‘__main__‘:
#     t = Thread(target=func1)
#     t.daemon = True  #  守护线程必须在start之前
#     t.start()
#     time.sleep(3)
#     t1 = Thread(target=func2)    #  普通线程
#     t1.start()
#     print("主线程")
#     print(t.is_alive())
#     print(t1.is_alive())

    # 守护线程是随着主线程执行结束而结束
    # 守护线程不是根据主线程的代码执行结束而结束
    # 主线程要等普通线程结束才结束
    # 所以,一般把不重要的事情设置为守护线程

#结果:
# 睡觉
# 主线程
# False
# True
# 吃饭


#  验证守护进程

# from multiprocessing import Process
# import time
# def func1():
#     time.sleep(2)
#     print("睡觉")
#
# def func2():
#     time.sleep(1)
#     print("吃饭")
# if __name__ == ‘__main__‘:
#     p = Process(target=func1)
#     p.daemon = True    # 守护进程
#     p.start()
#     p1 = Process(target=func2)
#     p1.start()
#     print(‘主进程‘)
#     print(p.is_alive())

#  守护进程是随着主进程代码块结束而结束.



#  锁
#锁和GIL
#同步锁
#  在多用户抢占资源的情况下

# from threading import Thread
# import time,os
#
# def func():
#     global n  # 定义全局变量
#     temp = n
#     time.sleep(0.1)
#     n = temp - 1
#     #print(n)
# if __name__ == ‘__main__‘:
#     n = 100
#     lst = []
#     for i in range(100):
#         t = Thread(target=func)
#         lst.append(t)
#         t.start()
#     [t.join() for t in lst]
#     print(n)
# 结果为 99

#  同步锁的引用:
# from threading import Thread,Lock
# import os,time
# def func(l):
#     global n
#     l.acquire()  #  上锁
#     temp = n
#     time.sleep(0.1)
#     n = temp - 1
#     l.release()
#
# if __name__ == ‘__main__‘:
#     l = Lock()
#     n = 100
#     lst = []
#     for i in range(100):
#         t = Thread(target=func,args=(l,))
#         lst.append(t)
#         t.start()
#     [t.join() for t in lst]
#     print(n)  # 结果是0 由原来的并发执行变成串行,牺牲了执行效率保证了数据安全


 #  互斥锁和join的区别

# 不加锁:并发执行,速度快,数据不安全
# from threading import Thread,Lock,current_thread
# import time,os
#
# def func():
#     global n
#     print(‘%s is running‘ %current_thread().getName())
#     temp = n
#     time.sleep(0.5)
#     n = temp -1
#
# if __name__ == ‘__main__‘:
#     n = 100
#     lst = []
#     start = time.time()
#     for i in range(100):
#         t = Thread(target=func)
#         lst.append(t)
#         t.start()
#     [t.join() for t in lst]
#     print(‘主:%s n:%s‘ %(time.time() - start,n))

#  结果:
# Thread-1 is running
# Thread-2 is running
#.......
# Thread-99 is running
# Thread-100 is running
# 主:0.5100293159484863 n:99
#

#  不加锁:未加锁部分并发执行,加锁部分串行,速度慢,数据安全
# from threading import current_thread,Thread,Lock
# import os,time
#
# def func():
#     #未加锁代码并发执行
#     time.sleep(4)
#     print("%s start to run" %current_thread().getName())
#     global n
#     # 加锁的代码串行运行
#     lock.acquire()
#     temp = n
#     time.sleep(0.5)
#     n = temp -1
#     lock.release
#
# if __name__ == ‘__main__‘:
#     n = 100
#     lock = Lock()
#     lst = []
#     start = time.time()
#     for i in range(100):
#         t = Thread(target=func)
#         lst.append(t)
#         t.start()
#     for t in lst:
#         t.join()
#     print("主:%s n:%s" %(time.time() - start,n))
#


#  死锁和递归锁
# 死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象
#诺无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些
#在相互等待的进程称为死锁进程
# 死锁代码:
# from threading import Lock
# import time
# muteAx = Lock()
# muteAx.acquire()
# muteAx.acquire()
# print(123)
# muteAx.release()
# muteAx.release()
# #  程序死锁等待
#解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供
#了可以重入锁RLock
# 这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,conger
#使得资源可以多次release.直到一个线程所有的acquire都被release,其他的线程才能获得资源

#  改进版

# from threading import RLock
# import time
# muteAx = RLock()
# muteAx.acquire()
# muteAx.acquire()
# print(123)
# muteAx.release()
# muteAx.release()

# 结果:123

#  典型问题,科学家吃面问题

# from threading import Thread ,Lock
# import time
# noodle_lock = Lock()
# fork_lock = Lock()
#
# def eat1(name):
#     noodle_lock.acquire()
#     print("%s抢到面条" %name)
#     fork_lock.acquire()
#     print(‘%s抢到叉子‘%name)
#     print(‘%s吃面‘%name)
#     fork_lock.release()
#     noodle_lock.release()
#
# def eat2(name):
#     fork_lock.acquire()
#     print(‘%s抢到叉子‘%name)
#     time.sleep(1)
#     noodle_lock.acquire()
#     print("%s抢到面条"%name)
#     print(‘%s吃面‘%name)
#     noodle_lock.release()
#     fork_lock.release()
#
# for name in [‘哪吒‘,‘egon‘,‘yuan‘]:
#     t1 = Thread(target=eat1,args=(name,))
#     t2 = Thread(target=eat2,args=(name,))
#     t1.start()
#     t2.start()
# 结果:程序卡住

#  解决递归死锁问题

# from threading import Thread,RLock
# import time
# fork_lock = noodle_lock = RLock()
#
# def eat1(name):
#     noodle_lock.acquire()
#     print("%s抢到面条了"%name)
#     fork_lock.acquire()
#     print("%s抢到了叉子"%name)
#     print(‘%s吃面‘%name)
#     fork_lock.release()  # 还叉子
#     noodle_lock.release() #   还面
#
# def eat2(name):
#     fork_lock.acquire()
#     print("%s抢到叉子"%name)
#     time.sleep(1)
#     noodle_lock.acquire()
#     print(‘%s抢到面条‘%name)
#     print(‘%s吃面‘%name)
#
# for name in [‘哪吒‘,‘alex‘,‘太白‘]:
#     t1 = Thread(target=eat1,args=(name,))
#
#     t2 = Thread(target=eat2,args=(name,))
#     t1.start()
#     t2.start()



#  信号量
#同进程的一样
#Semaphore管理一个内置的计数器
#每当调用acquire()时内置计算器-1
#调用release()时内置计数器+1
#计数器不能小于0,当计数器为0时,acquire()将阻塞线程直到其他线程调用release()
#实例:同时只有5个线程可以获得Semaphore即可以限制最大连接数为5个



# from threading import Thread,Semaphore
# import threading,time
#
# def func():
#     sm.acquire()
#     print(‘%s get sm‘%threading.current_thread().getName())
#     time.sleep(3)
#     sm.release()
#
# if __name__ == ‘__main__‘:
#     sm = Semaphore(5)
#     for i in range(10):
#         t = Thread(target=func)
#         t.start()


#  事件
#和进程的一样
#线程的一个关键性是每个线程都是独立运行且状态不可预测.如果程序中有其它线程需通过判断某个线程
#的状态来确定自己下一步操作,这时线程同步问题就会变的非常棘手.为了解决这些问题,我们需要
#使用threading库中的Event对象.对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的
#发生.在初始情况下Event对象中的信号标志被设置为假.如果有线程等待一个Event对象,而这个Event
#Event对象的标志为假,那么这个线程会被一直阻塞直到标志为真.一个线程如果将一个Event对象的
#信号标志设置为真,它将唤醒所有等待这个Event对象的线程.如果一个线程等待一个已经被设置为真
#的Event对象,那么它将忽略这个事件,继续执行

# event.isSet(): 返回Event的状态值
# event.wait():如果event.isSet()==False将阻塞线程
# event.set():设置event的状态值为True,所有阻塞池的线程激活进入就绪状态,等待操作系统调度
#
# event.clear():恢复event的状态值为False
#
#例如 有很多个工作线程尝试连接MySQL,我们想要在连接前确保MySQL服务正常才让那些工作线程去
#连接MySQL服务器,如果连接不成功,都会尝试重新连接.那么我们就可以采用htreading.Event机制
#来协调各个工作线程的连接操作

# from threading import Thread,Event
# import threading,time,random
#
# def conn_mysql():  #  连接服务器
#     count = 1
#     while not event.is_set():
#         if count > 3:
#             raise TimeoutError(‘链接超时‘)
#         print(‘第%s次尝试链接‘%(threading.current_thread().getName(),count))
#         event.wait(0.5)
#         count += 1
#     print("链接成功"%threading.current_thread().getName())
#
#
# def check_mysql():
#     print("\033[32m[%s]正在检查mysql\033[0m"%threading.current_thread().getName())
#     time.sleep(random.randint(1,3))
#     event.set()
#
#
# if __name__ == ‘__main__‘:
#     event = Event()
#     conn1 = Thread(target=conn_mysql)
#     conn2 = Thread(target=conn_mysql)
#     check = Thread(target=check_mysql())
#     conn1.start()
#     conn2.start()
#     check.start()
#
#


#  条件

#使得线程等待,只有满足条件时,才释放n个线程
#Python提供的Condition对象提供了对复杂线程同步问题的支持Condition被称为条件变量,除了
#提供与Lock类似的acquire和release方法外,还提供了wait和notify方法.线程首先acquire一个条件变量
#然后判断一些条件.如果条件不满足则wait,如果条件满足,进行一些处理改变条件后,通过notify方法通知
# 其他线程,其它处于wait状态的线程接到通知后会重新判断条件.不断的重复这一过程,从而解决复杂的问题

# from threading import Thread,Condition
#
# def run(n):
#     con.acquire()
#     con.wait()
#     print(‘run the thread:%s‘%n)
#     con.release()
#
# if __name__ == ‘__main__‘:
#     con = Condition()
#     for i in range(10):
#         t = Thread(target=run,args=(i,))
#         t.start()
#     while 1:
#         inp = input(">>>>")
#         if inp.upper() == "Q":
#             break
#         con.acquire()
#         con.notify(int(inp))
#         con.release()
#         print("****")

#   定时器

# 定时器,指定n秒后执行某个操作
# from threading import Timer
# Timer(time,func)
# time:睡眠的时间,以秒为单位
# func:睡眠时间之后,需要执行的任务

from threading import Timer

def hello():
    print(‘hello,world‘)

t = Timer(5,hello)    #  警示定时5秒执行函数hello
t.start()

  

Python线程

标签:串行   tpi   bre   cti   isa   while   为什么   字节码   打开   

原文地址:https://www.cnblogs.com/caodneg7/p/9535544.html


评论


亲,登录后才可以留言!