首页 > 编程语言 > 详细

网络编程之线程

时间:2020-06-14 09:49:13      阅读:45      评论:0      收藏:0      [点我收藏+]

线程

线程优点:

  • 数据共享,但数据不安全
  • 效率高开销小
  • 可以被多个cpu调度(是CPU调度的最小单位),由操作系统负责调度

数据共享:

  • Manager dict list 只要是共享的数据都存在数据不安全的现象
  • 需要我们自己加锁来解决数据安全问题

不安全现象:

  • += -= *= /= while if 数据不安全存在数据不安全
  • append pop strip数据安全 列表中的方法或者字典中的方法去操作全局变量的时候 数据安全的

GIL锁(全局解释锁):导致了同一个进程中的多个线程不能利用多核

守护线程

  • 其他子线程-->主线程结束-->主进程结束-->整个进程中所有的资源都被回收-->守护线程也会被回收
  • 如果主线程代码结束之后还有其他子进程在运行,守护线程守护
def func():
    print(‘线程‘)
t = Thread(target=func)
t.daemon = True  # 守护进程
t.start()
# 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。

互斥锁

  • 即多个线程抢占同一个数据(资源)时,保证数据的安全和合理的顺序。
from threading import Thread,Lock

x = 100
lock = Lock()

def task():
    global x
    lock.acquire()
    x -= 1
    print(x)
    lock.release()


if __name__ == ‘__main__‘:
    t_l1 = []
    for i in range(10):
        t = Thread(target=task)
        t_l1.append(t)
        t.start()

    for i in t_l1:
        i.join()
    print(f‘主{x}‘)

递归锁

  • 可递归获取多把锁和钥匙

死锁现象

死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁

  • 解决办法:递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock
from threading import Thread,RLock
lockA = lockB = RLock()

class MyThread(Thread):
    
    def run(self):
        self.f1()
        self.f2()
    
    def f1(self):
        lock_A.acquire()
        print(f‘{self.name}拿到A锁‘)
        
        lock_B.acquire()
        print(f‘{self.name}拿到B锁‘)
        lock_B.release()
        
        lock_A.release()
    
    def f2(self):
        lock_B.acquire()
        print(f‘{self.name}释放B锁‘)
        time.sleep(0.1)
        
        lock_A.acquire()
        print(f‘{self.name}释放A锁‘)
        lock_A.release()
        
        lock_B.release()


if __name__ == ‘__main__‘:
    for i in range(10):
        t = MyThread()
        t.start()
    
    print(‘主程序结束‘)

队列

  • queue模块
  • queue类----先进先出
import queue #不需要通过threading模块里面导入,直接import queue就可以了,这是python自带的
#用法基本和我们进程multiprocess中的queue是一样的
q=queue.Queue()
q.put(‘1‘)
q.put(‘2‘)
q.put(‘3‘)
# q.put_nowait() #没有数据就报错,可以用try
print(q.get())
print(q.get())
print(q.get())
# q.get_nowait() #没有数据就报错,可以用try
# 1  2  3
  • LifoQueue---栈(last in first out)
import queue

q=queue.LifoQueue() #队列,类似于栈,栈我们提过吗,是不是先进后出的顺序啊
q.put(‘1‘)
q.put(‘2‘)
q.put(‘3‘)
print(q.get())
print(q.get())
print(q.get())
# 3  2  1
  • PriorityQueue-------优先级队列
import queue

q=queue.PriorityQueue()
#put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
q.put((-10,‘a‘))
q.put((-5,‘a‘))  #负数也可以
# q.put((20,‘ws‘))  #如果两个值的优先级一样,那么按照后面的值的acsii码顺序来排序,如果字符串第一个数元素相同,比较第二个元素的acsii码顺序
# q.put((20,‘wd‘))
# q.put((20,{‘a‘:11})) #TypeError: unorderable types: dict() < dict() 不能是字典
# q.put((20,(‘w‘,1)))  #优先级相同的两个数据,他们后面的值必须是相同的数据类型才能比较,可以是元祖,也是通过元素的ascii码顺序来排序

q.put((20,‘b‘))
q.put((20,‘a‘))
q.put((30,‘c‘))
print(q.get())
print(q.get())
print(q.get())

信号量Semaphore

  • Semaphore管理一个内置的计数器
    • 每当调用acquire()时内置计数器-1;
    • 调用release() 时内置计数器+1;
    • 计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()
from threading import Thread,Semaphore
from threading import current_thread
import time
# 同时只有3个线程可以获得semaphore,即可以限制最大连接数为3
sem = Semaphore(3)

def func():
    sem.acquire()
    print(f‘{current_thread().getName()}阻塞一下‘)
    time.sleep(2)
    sem.release() 

if __name__ == ‘__main__‘:
    for i in range(20):
        t = Thread(target=func)
        t.start()

其他相关的方法

  • Thread实例对象的方法:
    • isAlive():返回线程是否活动的
    • getName():返回线程名
    • setName():设置线程名
  • threading模块提供的方法:
    • threading.currentThread():返回当前的线程变量
    • threading.enumerate():返回一个正在运行的线程的list。不包括启动前和终止后的线程
    • threading.activeCount():返回正在运行的线程数量,和上一个函数有相同的结果

网络编程之线程

原文:https://www.cnblogs.com/tonxin66/p/13123735.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!