• 多线程编程


    1. 进程和线程:

       进程是一个执行中的程序,每个进程都有自己的地址空间,内存,数据栈以及其他用于追踪执行的辅助数据。

       线程是在同一个进程下执行的,并共享相同的上下文。线程包括开始,执行顺序和结束三部分。一个线程中各个线程和主线程共用同一片数据空间,相比较独立的进程而言,线程间的信息共享和通信更加容易。线程一般是并发执行的。

       进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

       1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

       2) 线程的划分尺度小于进程,使得多线程程序的并发性高。

       3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

       4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

       5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

    2. 全局解释器锁:

       python在设计的时候,在主循环中同时只能有一个控制线程在执行(尽管python 解释器可以运行多个线程,但在任意给定时刻,只能有一个程序运行)。

       对python虚拟机的访问是全局解释器锁(GIL)控制的。这个锁就是用来保证同时只能有一个线程运行的。

              1.设置 GIL。

              2.切换进一个线程去运行。

              3.执行下面操作之一。

                 a.指定数量的字节码指令。

                 b.线程主动让出控制权(可以调用 time.sleep(0)来完成)。

              4.把线程设置回睡眠状态(切换出线程)。
              5.解锁 GIL。
              6.重复上述步骤

    3. python使用线程:

     1 import time
     2 import threading
     3 def loop1():
     4     print('Start loop 1 at : ', time.ctime())
     5     time.sleep(4)
     6     print('End loop 1 at : ', time.ctime())
     7 
     8 def loop2():
     9     print('Start loop 2 at : ', time.ctime())
    10     time.sleep(2)
    11     print('End loop 2 at : ', time.ctime())
    12 
    13 def main():
    14     print("Startig at : ", time.ctime())
    15     #loop1()
    16     #loop2()
    17     threading.Thread(loop1(),())
    18     threading.Thread(loop2(), ())
    19     time.sleep(6)
    20     print("All done at : ", time.ctime())
    21 
    22 if __name__ == '__main__':
    23     main()

    4. threading模块中的Thread类:

       threading 模块支持守护线程,其工作方式是:守护线程一般是一个等待客户端请求服务的服务器。如果没有客户端请求,守护线程就是空闲的。如果把一个线程设置为守护线程,就表示这个线程是不重要的,进程退出时不需要等待这个线程执行完成。 

       a. 创建Thread实例,传给它一个函数

     1 from time import ctime,sleep
     2 import threading
     3 
     4 loops = [4, 2]
     5 
     6 def loop(nloop, nsec):
     7     print('Start loop {0} at : {1}'.format(nloop+1, ctime()))
     8     sleep(nsec)
     9     print('End loop {0} at : {1}'.format(nloop+1, ctime()))
    10 
    11 def main():
    12     print("Startig at : ", ctime())
    13     threads = []
    14     nloops = range(len(loops))
    15 
    16     for i in nloops:
    17         t = threading.Thread(target=loop, args=(i, loops[i]))
    18         threads.append(t)
    19 
    20     for i in nloops:
    21         threads[i].start()
    22 
    23     for i in nloops:
    24         threads[i].join()
    25 
    26     print("All DONE at : ", ctime())
    27 
    28 if __name__ == '__main__':
    29     main()

       b. 创建Thread实例,传给它一个可以调用的类实例

     1 import threading
     2 from time import ctime,sleep
     3 
     4 loops = [4, 2]
     5 class ThreadFunc(object):
     6     def __init__(self, func, args, name=''):
     7         self.name = name
     8         self.func = func
     9         self.args = args
    10 
    11     def __call__(self):
    12         self.func(*self.args)
    13 
    14 def loop(nloop, nsec):
    15     print('Start loop {0} at : {1}'.format(nloop + 1, ctime()))
    16     sleep(nsec)
    17     print('End loop {0} at : {1}'.format(nloop + 1, ctime()))
    18 
    19 def main():
    20     print("Startig at : ", ctime())
    21     threads = []
    22     nloops = range(len(loops))
    23 
    24     for i in nloops:
    25         t = threading.Thread(target=ThreadFunc(loop, (i, loops[i]), loop.__name__))
    26         threads.append(t)
    27 
    28     for i in nloops:
    29         threads[i].start()
    30 
    31     for i in nloops:
    32         threads[i].join()
    33 
    34     print("All DONE at : ", ctime())
    35 
    36 if __name__ == '__main__':
    37     main()

    5. 锁:

       锁有两种状态:锁定和未锁定 

       只支持两个函数: 获得锁和释放锁

       当多线程开始挣锁时,允许第一个获得锁的线程进入临界区,并执行代码。所有之后到达的线程将阻塞,直到第一个线程执行结束,退出临界区,并释放锁。其他等待的线程获得锁并进入临界区,那些被阻塞的线程是没有顺序的,胜出线程的选择是不确定的。

     1 from atexit import register
     2 from random import randrange
     3 from threading import Thread, currentThread, Lock
     4 from time import sleep, ctime
     5 
     6 class CleaOutputset(set):
     7     def __str__(self):
     8         return (', '.join(x for x in self))
     9 
    10 lock = Lock()
    11 loops = (randrange(2, 5) for x in range(randrange(3, 7)))
    12 remaining = CleaOutputset()
    13 
    14 def loop(nsec):
    15     myname = currentThread().name
    16     lock.acquire()
    17     remaining.add(myname)
    18     print('[%s] Started %s' % (ctime(), myname))
    19     lock.release()
    20     sleep(nsec)
    21     lock.acquire()
    22     remaining.remove(myname)
    23     print('[%s] Completed %s (%d secs)' % (ctime(), myname, nsec))
    24     print('     (remaining: %s)' % (remaining or 'NONE'))
    25     lock.release()
    26 
    27 def main():
    28     for pause in loops:
    29         Thread(target=loop(), args=(pause,)).start()
    30 
    31 @register
    32 def atexit():
    33     print("All DONE at: ", ctime())
    34 
    35 if __name__ == '__main__':
    36     main()
  • 相关阅读:
    PyQt5对话框
    PyQt5基础控件
    PyQt5主界面
    PyQt5入门
    ioctl太多虚拟内存不够用
    code principles
    Error: watch ENOSPC
    intelJ
    cas
    C的函数指针的作用,以及其赋值是弱类型的
  • 原文地址:https://www.cnblogs.com/chengchengaqin/p/9722268.html
Copyright © 2020-2023  润新知