zoukankan      html  css  js  c++  java
  • 线程

    内容梗概:
    1.线程的定义,创建以及threading模块
    2.线程的一些其他方法
    3.进程与线程创建的效率对比
    4.线程间的数据共享
    5.死锁现象
    6.守护线程,事件,信号量

    1.线程的定义以及创建
    定义:
    进程是资源分配的最小单位,线程是CPU调度的最小单位.每一个进程中至少有一个线程。
    多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。
    线程与进程的区别:
       1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
       2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。(就类似进程中的锁的作用)
       3)调度和切换:线程上下文切换比进程上下文切换要快得多。
       4)在多线程操作系统中(现在咱们用的系统基本都是多线程的操作系统),进程不是一个可执行的实体,真正去执行程序的不是进程,是线程,你可以理解进程就是一个线程的容器。


    线程的创建以及threading模块:
    创建方式1:
    import os,time
    from threading import Thread
    def func(num):
    time.sleep(1)
    print('我是子线程,我的pid是',os.getpid())
    print("hei,girl")
    print(num)
    if __name__ == '__main__':
    t = Thread(target=func,args=(3,))
    t.start()
    print('主线程的pid',os.getpid()) #主线程和子线程都在同一个进程中

    创建方式2:
    import time
    from threading import Thread
    class mythread(Thread):
    def __init__(self,name):
    super().__init__()
    self.name = name
    def run(self):
    time.sleep(0.5)
    print("Hei girl,I am %s"%self.name)
    if __name__ == '__main__':
    t = mythread("王大锤")
    t.start()
    print('开始等待子线程了')
    t.join() #等待子线程结束才继续往下执行主线程
    print('主线程结束')


    2.线程的一些其他方法
    import time,threading
    from threading import current_thread,Thread
    def func(num):
    time.sleep(1)
    print("子线程名",current_thread().getName())
    print("子线程id", current_thread().ident)

    pass
    if __name__ == '__main__':
    t = Thread(target=func,args=(5,))
    t.start()
    print(threading.enumerate())
    print(threading.activeCount())


    3.进程与线程创建的效率对比
    import time
    from threading import Thread
    from multiprocessing import Process
    def func():
    print('Hei girl')
    if __name__ == '__main__':
    t_list = []
    t_s_t = time.time()
    for i in range(100):
    t = Thread(target=func, )
    t_list.append(t)
    t.start()
    [tt.join() for tt in t_list]
    t_e_t = time.time()
    t_dif_t = t_e_t - t_s_t

    p_list = []
    p_s_t = time.time()
    for i in range(100):
    p = Process(target=func, )
    p_list.append(p)
    p.start()
    [pp.join() for pp in p_list]
    p_e_t = time.time()
    p_dif_t = p_e_t - p_s_t
    print('多线程的时间>>>', t_dif_t)
    print('多进程的时间>>>', p_dif_t)
    # 多线程的时间>>> 0.019013404846191406
    # 多进程的时间>>> 4.62909722328186
    总结:创建进程很慢,所需资源较多,而创建线程很快,不需要什么资源,且线程内数据共享


    4.线程之间的数据共享

    4.1.线程之间的数据是可以共享的,但是不安全的(要保证安全需要加锁)
    import time
    from threading import Thread,Lock

    num = 100
    def func():
    global num
    lock.acquire()
    tep = num
    time.sleep(0.01)
    tep = tep - 1
    num = tep
    lock.release()

    if __name__ == '__main__':
    lock = Lock()
    t_list = []
    for i in range(100):
    t = Thread(target=func, )
    t_list.append(t)
    t.start()
    [tt.join() for tt in t_list]
    print('主线程的num',num)


    5.死锁现象
    可采用递归锁解决
    import time
    from threading import Thread,Lock,RLock

    def func1(lock_A,lock_B):
    lock_A.acquire()
    time.sleep(0.5)
    print('alex拿到了A锁')
    lock_B.acquire()
    print('alex拿到了B锁')
    lock_B.release()
    lock_A.release()

    def func2(lock_A,lock_B):
    lock_B.acquire()
    print('taibai拿到了B锁')
    lock_A.acquire()
    print('taibai 拿到了A锁')
    lock_A.release()
    lock_B.release()

    if __name__ == '__main__':
    lock_A = Lock() #普通锁这样会产生死锁
    lock_B = Lock()
    lock_A = lock_B = RLock() #采用递归锁可解决死锁现象
    t1 = Thread(target=func1,args=(lock_A,lock_B))
    t2 = Thread(target=func2,args=(lock_A,lock_B))
    t1.start()
    t2.start()



    6.守护线程,事件,信号量
    6.1守护线程
    tips:记住 主线程需等待非守护线程执行完毕才会结束
    import time
    from threading import Thread
    from multiprocessing import Process
    def func1():
    time.sleep(3)
    print("线程1结束啦")

    def func2():
    time.sleep(2)
    print("线程2结束啦")
    if __name__ == '__main__':
    t1 = Thread(target=func1)
    t2 = Thread(target=func2)
    # t1.daemon = True
    t1.start()
    t2.start()
    print("主线程结束啦")

    #和守护进程对比
    p1 = Process(target=func1, )
    p2 = Process(target=func2, )
    p1.daemon = True
    p2.daemon = True
    p1.start()
    p2.start()

    通过上面的对比发现:
    1.守护进程,主进程代码运行完毕后,守护进程会一起结束,而主进程会等非守护进程结束才真正结束
    2.守护线程,(主线程需等待非守护线程执行完毕才会结束),即主线程代码运行完了,也不会直接结束守护线程,而要等其他非守护线程执行完,主线程结束,才会结束守护线程


    4.2事件
    跟进程的事件基本一致

    from threading import Thread,Event

    e = Event() #默认是False,

    print(e.isSet())
    print('开始等啦')
    e.set() #将事件对象的状态改为True
    print(e.isSet())
    e.clear() #将e的状态改为False

    e.wait() #如果e的状态为False,就在这里阻塞
    print('大哥,还没完事儿,你行')

    4.3信号量
    import time
    import random
    from threading import Thread,Semaphore

    def func(i,s):
    s.acquire()
    print('客官%s里边请~~' % i)
    time.sleep(random.random())
    s.release()
    if __name__ == '__main__':
    s = Semaphore(4) #上锁,但允许一次四个人使用锁
    for i in range(10):
    t = Thread(target=func,args=(i+1,s))
    t.start()
  • 相关阅读:
    Mybatis主配置文件常见使用讲解
    Mybatis导入原生配置文件
    分页查询时,使用cookie保存上次的查询条件。jQuery实现方法以及中间遇到的坑
    jQuery实现checkbox即点即改,批量计数,以及中间遇到的坑
    ()IT 职场经验)一位10年Java工作经验的架构师的经验分享,感觉很受用。
    SpringMVC的Controller
    Spring MVC执行原理和基于Java的配置过程
    集成学习综述笔记
    generalization error
    Failed to install 'unknown package' from GitHub: schannel: failed to receive handshake, SSL/TLS connection failed
  • 原文地址:https://www.cnblogs.com/Mixtea/p/10045575.html
Copyright © 2011-2022 走看看