进程 && 线程
进程:进程是操作系统中执行的一个程序,操作系统以进程为单位分配存储空间,每个进程都有自己的地址空间、数据栈以及其他用于跟踪进程执行的辅助数据,操作系统管理所有进程的执行,为它们合理的分配资源。进程可以通过fork或者wpawn的方式来创建新的进程执行其他任务,不过新的进程有自己独立的内存空间和数据栈,所以必须通过进程间的通信机制(IPC,Inter Process Communication)来实现数据共享,具体的方式包括管道、信号、套接字、共享内存等。
线程:进程的一个执行单元。线程在同一个进程中执行,共享程序的上下文。一个进程中的各个线程与主线程共享同一片数据空间,因而相比与独立的进程,线程间的信息共享和通信更为容易。线程一般是以并发的方式执行的。注意在单核CPU系统中,真正的并发是不可能的,所以新城的执行实际上是这样规划的:每个线程执行一小会,然后让步给其他线程的任务(再次排队等候更多的CPU执行时间)。在整个线程的执行过程中,每个线程执行它自己的特定的任务,在必要时和其他进程进行结果通信。
Python多进程(使用multiprocessing) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from time import time, sleepfrom random import randintfrom multiprocessing import Processdef my_task (name ): sleep_time = randint(1 ,10 ) sleep(sleep_time) print ("你叫了一声%s,它鸟你用了%d秒" % (name, sleep_time)) def main (): start = time() process_1 = Process(target=my_task, args=["yeshan" , ]) process_2 = Process(target=my_task, args=["foel" , ]) process_1.start() process_2.start() process_1.join() process_2.join() end = time() print ("一共花费了%f秒" % (end-start)) if __name__ == '__main__' : main()
我们通过Process类创建了进程对象,通过target
参数我们传入一个函数来表示进程启动后要执行的代码,后面的args
是一个元组,它代表了传递给函数的参数。 Process对象的start方法用来启动进程,join方法表示等待进程执行结束。
Python多线程(使用threading) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 from time import time, sleepfrom random import randintfrom threading import Threaddef download (filename ): print ("开始下载 %s ..." % filename) download_time = randint(1 ,10 ) sleep(download_time) print ("下载完成!耗时 %d 秒" % download_time) def main (): start = time() t1 = Thread(target=download, args=('黑暗地宫' ,)) t1.start() t2 = Thread(target=download, args=('通天' ,)) t2.start() t1.join() t2.join() end = time() print ("下载总共耗时 %.3f 秒" % (end-start)) if __name__ == '__main__' : main()
** 继承Thread类,实现自定义线程类 **
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 from time import time, sleepfrom random import randintfrom threading import Threadclass DownLoadTask (Thread ): def __init__ (self, filename ): super ().__init__() self._filename = filename def run (self ): print ("开始下载 %s ..." % self._filename) download_time = randint(1 ,10 ) sleep(download_time) print ("%s下载完成!耗时 %d 秒" % (self._filename, download_time)) def main (): strat = time() t1 = DownLoadTask("从菜鸟到菜鸡" ) t1.start() t2 = DownLoadTask("去哪里啊弟弟" ) t2.start() t1.join() t2.join() end = time() print ("下载完成,总共耗费 %.3f 秒" % (end-strat)) if __name__ == '__main__' : main()
线程间的通信
因为多个线程可以共享进程的内存空间,因此要实现多个线程间的通信相对简单,大家能想到的最直接的办法就是设置一个全局变量,多个线程共享这个全局变量即可。但是当多个线程共享同一个变量(我们通常称之为“资源”)的时候,很有可能产生不可控的结果从而导致程序失效甚至崩溃。如果一个资源被多个线程竞争使用,那么我们通常称之为“临界资源”,对“临界资源”的访问需要加上保护,否则资源会处于“混乱”的状态。在这种情况下,“锁”就可以派上用场了。我们可以通过“锁”来保护“临界资源”,只有获得“锁”的线程才能访问“临界资源”,而其他没有得到“锁”的线程只能被阻塞起来,直到获得“锁”的线程释放了“锁”,其他线程才有机会获得“锁”,进而访问被保护的“临界资源”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 from time import sleepfrom threading import Thread, Lockclass Account (object ): def __init__ (self ): self._balance = 0 self._lock = Lock() def deposit (self, money ): self._lock.acquire() try : new_balance = self._balance + money sleep(0.01 ) self._balance = new_balance finally : self._lock.release() @property def balance (self ): return self._balance class AddMoneyThread (Thread ): def __init__ (self, account, money ): super ().__init__() self._account = account self._money = money def run (self ): self._account.deposit(self._money) def main (): account = Account() threads = [] for _ in range (100 ): t = AddMoneyThread(account, 1 ) threads.append(t) t.start() for t in threads: t.join() print ('账户余额为: ¥%d元' % account.balance) if __name__ == '__main__' : main()
输出结果为100块,不用锁为2块
** Python内置装饰器 property **
*** property装饰器一般存在于类中,可以将一个函数定义成一个属性,属性的值就是该函数return的内容 ***
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Student (object ): @property def score (self ): return self._score @score.setter def score (self, value ): if not isinstance (value, int ): raise ValueError('score must be an integer!' ) if value < 0 or value > 100 : raise ValueError('score must between 0 ~ 100!' ) self._score = value
参考:
一篇文章搞懂装饰器的用法
https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/Day13/%E8%BF%9B%E7%A8%8B%E5%92%8C%E7%BA%BF%E7%A8%8B.md