zoukankan      html  css  js  c++  java
  • 并发编程之多线程

    1.什么是线程?

    线程指的是程序的执行线路,相当于一条流水线,包含了程序的具体执行步骤,一条流水线必须属于一个车间,一个车间的工作过程就是一个进程,车间负责把资源整合到一起,是一个资源单位,而车间内至少有一条流水线,也就是说一个进程至少有一个线程。

    进程是一个资源单位,线程是CPU的最小执行单位。

    线程和进程的关系:进程包含了运行程序需要的所有资源,每一个进程一旦被创建,就默认开启了一条线程,称之为主线程。一个进程可以包含多个线程,而线程依赖进程。

    2.什么是多线程?

    多线程指的是在一个进程中存在多个线程,多个线程共享该进程的地址空间,相当于一个车间内有多条流水线,都公用一个车间的资源。

    注:多进程之间内存地址是相互隔离的,多线程之间的资源是共享的。

    3.为什么使用多线程?

    因为多进程对操作系统的资源耗费非常高,每开一个进程都要申请内存空间,而开线程,就相当于在一个车间内造一条流水线,无需申请空间,对操作系统的资源耗费比较小。多线程可以使CPU在一个进程内进行切换,从而提到CPU的占用率,从而提高程序的效率。

    应用场景:当遇到I/O操作时,就可以使用多线程。

    进程和线程的区别:

    1.进程对于操作系统的资源耗费非常高,而线程相反(比进程低10-100倍)。

    2.在同一个进程中,多个线程之间资源共享的;多个进程之间,内存是相互隔离的,即资源不共享。

    4.开启线程的两种方式

    1.实例化Thread类的对象

    from threading import Thread
    
    def task():
        print('子线程。。。')
    
    t = Thread(target=task)
    t.start()
    print('')
    
    # 子线程。。。  # 由于开启线程的速度非常快,所以有可能的情况就是子线程一经开启,就立马执行其中代码
    #

    2.继承Thread类,覆盖run方法

    class MyThread(Thread):
        def run(self):
            print("子线程 running....")
    MyThread().start()
    print("over2")

    5.多进程和多线程对比

    1.开启速度

    from threading import Thread
    import time
    def task():
        pass
    start = time.time()
    l = []
    for i in range(100):
        t = Thread(target=task)
        l.append(t)
        t.start()
    print(time.time()-start)
    for t in l:
        t.join()
    print('')
    
    # 0.015770673751831055
    #
    开启多个线程
    from multiprocessing import Process
    import time
    def task():
        pass
    
    l = []
    if __name__ == '__main__':
        start = time.time()
        for i in range(100):
            p = Process(target=task)
            l.append(p)
            p.start()
        print(time.time()-start)
        for p in l:
            p.join()
        print('')
    
    # 3.595005750656128
    #
    开启多个进程

    2.PID

    from multiprocessing import Process
    import time
    import os
    
    def task1():
        print(os.getpid())  # 9528
    def task2():
        print(os.getpid())  # 11704
    
    
    if __name__ == '__main__':
        p1 = Process(target=task1)
        p1.start()
        p2 = Process(target=task2)
        p2.start()
    多进程的PID
    from threading import Thread
    import time
    import os
    
    def task1():
        print(os.getpid())  # 7560
    def task2():
        print(os.getpid())  # 7560
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task1)
        t1.start()
        t2 = Thread(target=task2)
        t2.start()
    多线程的PID

    3.数据共享

    from threading import Thread
    
    x = 100
    def task():
        global x
        x = 0
    l = []
    for i in range(100):
        t = Thread(target=task)
        t.start()
        l.append(t)
    for t in l:
        t.join()
    print(x)
    print('over')
    
    
    # 0
    # over
    多线程间数据共享
    from multiprocessing import Process
    
    x = 100
    def task():
        global x
        x = 0
    l = []
    if __name__ == '__main__':
    
        for i in range(100):
            t = Process(target=task)
            t.start()
            l.append(t)
        for t in l:
            t.join()
        print(x)
        print('over')
    
    # 100
    # over
    进程间数据数据不共享

    6.线程相关的其他方法

    Thread实例对象的方法
      # isAlive(): 返回线程是否活动的。
      # getName(): 返回线程名。
      # setName(): 设置线程名。
    
    threading模块提供的一些方法:
      # threading.currentThread(): 返回当前的线程变量。
      # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
      # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
    from threading import Thread
    import threading
    from multiprocessing import Process
    import os
    
    def work():
        import time
        time.sleep(3)
        print(threading.current_thread().getName())
    
    
    if __name__ == '__main__':
        #在主进程下开启线程
        t=Thread(target=work)
        t.start()
    
        print(threading.current_thread().getName())
        print(threading.current_thread()) #主线程
        print(threading.enumerate()) #连同主线程在内有两个运行的线程
        print(threading.active_count())
        print('主线程/主进程')
    
        '''
        打印结果:
        MainThread
        <_MainThread(MainThread, started 140735268892672)>
        [<_MainThread(MainThread, started 140735268892672)>, <Thread(Thread-1, started 123145307557888)>]
        主线程/主进程
        Thread-1
        '''
    View Code

    7.守护线程

    守护线程会在所有非守护线程结束后结束。主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时进行回收),因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。

    from threading import Thread
    import time
    
    
    def task():
        print('子线程 run....')
        time.sleep(0.1)
        print('子线程 over...')
    
    
    t = Thread(target=task)
    t.daemon = True  # 必须在start前
    t.start()
    print('主线程 over...')
    
    # 子线程 run....
    # 主线程 over...
    from threading import Thread
    import time
    def task1():
        print('子线程1 run....')
        time.sleep(0.1)
        print('子线程1 over...')
    def task2():
        print('子线程2 run....')
        # time.sleep(1)
        print('子线程2 over...')
    
    t1 = Thread(target=task1)
    t2 = Thread(target=task2)
    t1.daemon = True  # 必须在start前
    t1.start()
    t2.start()
    print('主线程 over...')
    
    # 子线程1 run....
    # 子线程2 run....
    # 子线程2 over...
    # 主线程 over...
    例2

    8.线程互斥锁

    当多个线程需要同时修改同一份数据时,可能会造成数据错乱,所以这时必须加锁。

    from threading import Thread,Lock
    import time
    lock = Lock()
    x = 100
    def task():
        lock.acquire()
        global x
        t = x - 1
        time.sleep(0.01)
        x = t
        lock.release()
    
    l = []
    for i in range(100):
    
        t = Thread(target=task)
        t.start()
        l.append(t)
    for t in l:
        t.join()
    print(x)
    print('over')
    
    
    # 0
    # over
    线程互斥锁

    信号量:也是一种锁,其特点是可以设置一个数据可以被几个线程(进程)共享,即可以让这个数据在同一时间能被多个线程使用。它的应用场景是可以限制一个数据被同时访问的次数,保证程序正常运行。

    from threading import Thread,Semaphore,current_thread
    import time
    sem = Semaphore(4)  # 其中的参数可以设置有几个线程可以同时共享数据
    def task():
        sem.acquire()
        print('%s run...' % current_thread())
        time.sleep(2)
        sem.release()
    
    for i in range(10):
        t = Thread(target=task)
        t.start()

    线程互斥锁与信号量图解

    http://url.cn/5DMsS9r
  • 相关阅读:
    Hadoop(十六)之使用Combiner优化MapReduce
    Hadoop(十五)MapReduce程序实例
    Hadoop(十四)MapReduce原理分析
    STM32新的IDE -- stm32cubeIde 点亮个LED灯
    resin+spring-websocket 深坑
    spring Websocket 报 No suitab le default RequestUpgradeStrategy found
    nginx代理内网域名碰到的坑
    Showing Recent Issues clang: error: linker command failed with exit code 1 (use -v to see invocatio
    sublime安装插件步骤
    tomcat7 ajax请求服务中文乱码
  • 原文地址:https://www.cnblogs.com/wangke0917/p/10209175.html
Copyright © 2011-2022 走看看