• 并发编程


    一、计算机发展史

     1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式。此时还没有操作系统的概念。

      程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把程序和数据输入计算机内存,接着通过控制台开关启动程序针对数据运行;计算完毕,打印机输出计算结果;用户取走结果并卸下纸带(或卡片)后,才让下一个用户上机。

      手工操作方式两个特点:

      (1)用户独占全机。不会出现因资源已被其他用户占用而等待的现象,但资源的利用率低。
      (2)CPU 等待手工操作。CPU的利用不充分。
    二、多道程序系统
    所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行。即同时把多个程序放入内存,并允许它们交替在CPU中运行,它们共享系统中的各种硬、软件资源。当一道程序因I/O请求而暂停运行时,CPU便立即转去运行另一道程序。

          在A程序计算时,I/O空闲, A程序I/O操作时,CPU空闲(B程序也是同样);必须A工作完成后,B才能进入内存中开始工作,两者是串行的,全部完成共需时间=T1+T2。

          
          将A、B两道程序同时存放在内存中,它们在系统的控制下,可相互穿插、交替地在CPU上运行:当A程序因请求I/O操作而放弃CPU时,B程序就可占用CPU运行,这样 CPU不再空闲,而正进行A I/O操作的I/O设备也不空闲,显然,CPU和I/O设备都处于“忙”状态,大大提高了资源的利用率,从而也提高了系统的效率,A、B全部完成所需时间<<T1+T2。
          多道程序设计技术不仅使CPU得到充分利用,同时改善I/O设备和内存的利用率,从而提高了整个系统的资源利用率和系统吞吐量(单位时间内处理作业(程序)的个数),最终提高了整个系统的效率。
      单处理机系统中多道程序运行时的特点:
      (1)多道:计算机内存中同时存放几道相互独立的程序;
      (2)宏观上并行:同时进入系统的几道程序都处于运行过程中,即它们先后开始了各自的运行,但都未运行完毕;
      (3)微观上串行:实际上,各道程序轮流地用CPU,并交替运行。
     
    多道技术
      1.空间上的复用
        多个程序公用一套计算机硬件
    2.时间上的复用
      切换+保存状态
        1.当一个程序遇到IO操作,操作系统会剥夺改程序的cpu执行权限(提高了cpu的利用率,并且也不影响程序的执行效率)
      2.当一个程序长时间占用cpu,操作系统也会剥夺该程序的cpu执行权限(降低了程序的执行效率)
    并发:看起来像同时运行的就可以
    并行:真正意义上的同时执行,单核的计算机不能实现并行,但是可以实现并发
    三、创建进程的两种方式
      1.第一种创建进程的方式
     1 import time
     2 from multiprocessing import Process
     3 
     4 
     5 def test(name):
     6     print('%s is running'%name)
     7     time.sleep(3)
     8     print('%s is over'%name)
     9 
    10 #windows创建进程会将代码以模块的方式,从上往下执行一遍
    11 
    12 #windows创建进程一定要在if __name__ == '__main__':代码块内创建 否则报错
    13 if __name__ == '__main__':
    14     p = Process(target=test,args=('egon',))
    15     p.start() #告诉操作系统帮你创建一个进程
    16     print('')

    总结:

    创建进程就是在内存中重新开辟一块内存空间

    将允许产生的代码丢进去

    一个进程对应在内存就是一块独立的内存空间

    进程与与进程之间数据是隔离的,无法直接交互

    但是可以通过某些技术实现间接交互 

    2.第二种创建进程的方式

     1 from multiprocessing import Process
     2 import time
     3 
     4 class MyProcess(Process):
     5     def __init__(self,name):
     6         super().__init__()
     7         self.name = name
     8 
     9     def run(self):
    10         print('%s is run'%self.name)
    11         time.sleep(3)
    12         print('%s is over'%self.name)
    13         
    14 
    15 if __name__ == '__main__':
    16     p = MyProcess('egon')
    17     p.start()
    18     print('')

    四、join方法

     1 from multiprocessing import Process
     2 import time
     3 
     4 def test(name,i):
     5     print('%s is running'%name)
     6     time.sleep(i)
     7     print('%s is over'%name)
     8 
     9 if __name__ == '__main__':
    10     p_list = []
    11     p = Process(target=test,args=('tank',1))
    12     p1 = Process(target=test,args=('jason',2))
    13     p2 = Process(target=test,args=('jerry',3))
    14     start_time = time.time()
    15     p.start() #仅仅是告诉操作系统帮你创建一个进程,至于这个进程什么时候创,操作随机决定
    16     p1.start()
    17     p2.start()
    18     p.join()
    19     p1.join()
    20     p2.join()
    21 
    22     #主进程代码等待子进程运行结束,才继续执行
    23     #p.join() #主进程代码等待子进程运行结束
    24     print('')
    25     print(time.time()-start_time)

    五、进程间数据是隔离的

     1 from multiprocessing import  Process
     2 import time
     3 
     4 money = 100
     5 
     6 def test():
     7     global money
     8     money = 9999999
     9 
    10 if __name__ == '__main__':
    11     p = Process(target=test)
    12     p.start()
    13     p.join()
    14     print(money)

    六、进程对象及其他方法

     1 from multiprocessing import Process,current_process
     2 import os
     3 import time
     4 
     5 def test(name):
     6     print('%s is running'%name,'子进程%s'%os.getpid(),'父进程%s'%os.getpid())
     7     time.sleep(3)
     8     print('%s is over'%name)
     9 
    10 if __name__ == '__main__':
    11     p = Process(target=test,args=('egon',))
    12     p.start()
    13     p.terminate() #杀死当前进程,其实是告诉操作系统帮你杀死一个进程
    14     time.sleep(0.1)
    15     print(p.is_alive()) # 判断进程是否存活
    16     print('',os.getpid(),'主主进程:%s'%os.getppid())

    七、守护进程

     1 from multiprocessing import Process
     2 import time
     3 
     4 def test(name):
     5     print('下属%s正常运行'%name)
     6     time.sleep(3)
     7     print('下属%s正常关闭'%name)
     8 
     9 if __name__ == '__main__':
    10     p = Process(target=test,args=('egon',))
    11     p.daemon = True # 将该进程设置为守护进程,这一句话必须放在start语句之前,否则就报错
    12     p.start()
    13     time.sleep(0.1)
    14     print('领导已正常终止')

    当主进程正常死亡时,那么子进程必须跟着一起终止

    八、互斥锁

     1 from multiprocessing import Process,Lock
     2 import time
     3 import json
     4 
     5 def search(i):
     6     with open('data.txt','r',encoding='utf-8') as f:
     7         data = f.read()
     8     t_d = json.loads(data)
     9     print('用户%s查询余票:%s'%(i,t_d['ticket']))
    10 
    11 def buy(i):
    12     with open('data.txt','r',encoding= 'utf-8') as f:
    13         data = f.read()
    14     t_d = json.loads(data)
    15     time.sleep(1)
    16     if t_d.get('ticket') == 1:
    17         t_d['ticket'] -= 1
    18         with open('data.txt','w',encoding='utf-8') as f:
    19             json.dump(t_d,f)
    20         print('用户%s抢票成功!'%i)
    21     else:
    22         print('用户%s抢票失败,没票了'%i)
    23 
    24 def run(i,mutex):
    25     search(i)
    26     mutex.acquire() # 抢锁 只要有人抢到锁 其他人必须等待该人释放锁
    27     buy(i)
    28     mutex.release() # 释放锁
    29 
    30 if __name__ == '__main__':
    31     mutex = Lock() # 生成了一把锁
    32     for i in range(1,10):
    33         p = Process(target=run,args=(i,mutex))
    34         p.start()
  • 相关阅读:
    对面向对象设计原则的总结
    sql server连接字符串
    js页面加载进度条
    Yui.Compressor高性能ASP.NET开发:自动压缩CSS、JS
    asp.net利用多线程执行长时间的任务,客户端显示出任务的执行进度的示例(一)_转
    asp.net删除目录,Session丢失
    extjs ComboBox使用注意
    转:使Eclipse的智能感知可以像 Visual Studio 一样快速提示
    Android ContentProvider 填删改查 实例
    Windows Phone StackPanel 布局示例
  • 原文地址:https://www.cnblogs.com/spencerzhu/p/11333112.html
Copyright © 2020-2023  润新知