操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁

摘要:
2) 网络框架djangogflashtornado源代码并发编程3)套接字服务器源代码并发程序2。操作和维护领域1)自动开发操作和维护开发(机器批次管理)。

并发编程前言:

      1、网络应用

           1)爬虫 直接应用并发编程;

           2)网络框架 django flask tornado 源码-并发编程

           3)socketserver 源码-并发编程

      2、运维领域

           1)自动化开发-运维开发(机器的批量管理,任务的批量执行等)

一、操作系统/应用程序

a、硬件

       - 硬盘

       - CPU

       - 主板

       - 显卡

       - 内存

       - 电源

       . . . . . .

b、装系统(软件)

       - 系统就是一个由程序员写出来的软件,该软件用于控制计算机的硬件,让他们之间进行相互配合。

c、安软件(安装应用程序)

       - QQ

       - 百度云

       - pycharm

       . . . . . .

二、并行与并发

       并发,是伪的,由于执行速度特别快,人感觉不到停顿;

       并行,是真的,创建10个人同时操作;

       并行是指两者同时执行,比如赛跑,两个人都在不停的往前跑(资源够用,比如三个线程,四核的cpu);

       并发是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核cpu资源)同时只能过一个人,A走一段后,让给B,B用完继续给A,交替使用,目的是提高效率;

区别:

       并行是从微观上,也就是在一个精确的时间片刻,有不同的程序在执行,这就要求必须有多个处理器。

       并发是从宏观上,在一个时间段上可以看成是同时执行的。

三、线程和进程

a、单进程、单线程的应用程序,比如:

  print('666')

b、到底什么是线程?什么是进程?

       python自己没有这玩意,python中调用的操作系统的线程和进程。

c、单进程、多线程的应用程序,比如:

    import threading
    print('666')

    def func(arg):
        print(arg)
    t = threading.Thread(target=func,args=(11,)) # 创建一个线程
    t.start()

  一个应用程序(软件),可以有多个进程(默认只有一个),一个进程中可以创建多个线程(默认一个)。

d、故事:Alex甄嬛西游传

总结:

       1)操作系统帮助开发者操作硬件;

       2)程序员写好代码在操作系统上运行(依赖解释器);

       3)任务比较多时,可将以前代码写法作如下改进:

操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第1张操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第2张
    import requests
    import uuid

    url_list = [
'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
    ]

    def task(url):
        ret = requests.get(url)
        file_name = str(uuid.uuid4()) + '.jpg'
        with open(file_name, mode='wb') as f:
            f.write(ret.content)

    for url in url_list:
        task()
    """
    - 我们写好代码
    - 交给解释器运行: python s1.py 
    - 解释器读取代码,再交给操作系统去执行,根据我们的代码去选择创建多少个线程/进程去执行(此程序是单进程/单线程)。
    - 操作系统调用硬件:硬盘、cpu、网卡....
    """
以前的我们写代码
操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第3张操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第4张
    import threading
    import requests
    import uuid

    url_list = [
'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
    ]

    def task(url):
        ret = requests.get(url)
        file_name = str(uuid.uuid4()) + '.jpg'
        with open(file_name, mode='wb') as f:
            f.write(ret.content)

    for url in url_list:
        t = threading.Thread(target=task, args=(url,)) # 创建线程
        t.start()
    """
    - 你写好代码
    - 交给解释器运行: python s2.py 
    - 解释器读取代码,再交给操作系统去执行,根据你的代码去选择创建多少个线程/进程去执行(此程序是单进程/4线程)。
    - 操作系统调用硬件:硬盘、cpu、网卡....
    """
现在的我们写代码

四、python中线程和进程(GIL锁)

       GIL锁:python内置的一个全局解释器锁。用于限制一个进程中同一时刻只有一个线程被cpu调度。

       扩展:默认GIL锁再执行100个cpu指令(过期时间)。

操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第5张操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第6张
    import sys
    v = sys.getcheckinterval()
    print(v)  # 100
查看方法

  问题1:为什么有这把GIL锁?

              python语言的创始人在开发这门语言时,目的是快速把语言开发出来,如果加上GIL锁(c语言加锁),切换时按照100条字节指令来进行线程间的切换。

       问题2:进程和线程的区别?

              线程,线程是cpu工作的最小单元;

              进程,进程是cpu资源分配的最小单元,为线程提供一个资源共享的空间;

              一个进程中可以有多个线程,一个进程中默认有一个主线程;

              对于python来说,它的进程和线程和其他语言有差异,有GIL锁。它保证一个进程中同一时刻只有一个线程被cpu调度;

              IO密集型操作可以使用多线程,计算密集型可以使用多进程;

  问题3:线程创建的越多越好吗?

              不是,线程之间进行切换,要做上下文管理。

五、python线程编写

1、线程的基本使用,如下示例:

  import threading
  def func(arg):
      print(arg)

  t = threading.Thread(target=func,args=(11,)) # 创建一个子线程
  t.start()

  print(123)
  # 11
  # 123
  # 程序结束

2、主线程默认等子线程执行完毕,才结束程序,如下示例:

    import threading
    import time
    def func(arg):
        time.sleep(arg)
        print(arg)

    t1 = threading.Thread(target=func,args=(3,))
    t1.start()

    t2 = threading.Thread(target=func,args=(6,))
    t2.start()
    # 3  # 程序开始3秒后
    # 6  # 程序开始6秒后
    # 程序结束

3、主线程不再等,当主线程终止则所有子线程也终止,使用setDaemon(True),如下示例:

    import threading
    import time
    def func(arg):
        time.sleep(arg)
        print(arg)

    t1 = threading.Thread(target=func,args=(3,))
    t1.setDaemon(False)  # 主线程等待此子进程
    t1.start()

    t2 = threading.Thread(target=func,args=(6,))
    t2.setDaemon(True)  # 主线程不再等待此子进程
    t2.start()

    print(123)
    # 123
    # 3
    # # 程序结束

4、开发者可以控制主线程等待子线程(最多等待时间),使用join(n),如下示例:

    import threading
    import time
    def func(arg):
        time.sleep(arg)
        print(arg)

    print('创建子线程t1')
    t1 = threading.Thread(target=func,args=(3,))
    t1.start()
    t1.join(2)
    # 无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。
    # 有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。

    print('创建子线程t2')
    t2 = threading.Thread(target=func,args=(1,))
    t2.start()
    t2.join(3) # 让主线程在这里等着,最多等待3秒,会继续往下走,
    # 若子线程t2不到3秒就执行完毕,则子线程执行完毕主线程就往下走。

    print(123)
    # 创建子线程t1
    # 创建子线程t2
    # 3
    # 1
    # 123
    # 程序结束

5、线程名称,如下示例:

    import threading
    def func(arg):
        t = threading.current_thread()  # 获取当前执行该函数的线程的对象
        name = t.getName()  # 根据当前线程对象获取当前线程名称
        print(name,arg)

    t1 = threading.Thread(target=func,args=(11,))
    t1.setName('郭德纲')  # 设置线程名称
    t1.start()

    t2 = threading.Thread(target=func,args=(22,))
    t2.setName('孙红雷')  # 设置线程名称
    t2.start()

    print(123)
    # 郭德纲 11
    # 孙红雷 22
    # 123

6、线程本质,如下示例:

    # 先打印:11?123?
    import threading
    def func(arg):
        print(arg)

    t1 = threading.Thread(target=func,args=(11,))
    t1.start()
    # start 是开始运行线程吗?不是
    # start 告诉cpu,我已经准备就绪,你可以调度我了。
    print(123)

7、面向对象版本的多线程,如下示例:

操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第7张操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第8张
    import threading
    def func(arg):
        print(arg)

    t1 = threading.Thread(target=func,args=(11,))
    t1.start()
常见创建多线程的方式:
操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第9张操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁第10张
    import threading
    class MyThread(threading.Thread):
        def run(self):
            print(11111,self._args,self._kwargs)

    t1 = MyThread(args=(11,))
    t1.start()  # 在cpu内部,如果要调度这个线程的话会执行这个对象的run方法

    t2 = MyThread(args=(22,))
    t2.start()

    print('end')
    # 11111 (11,) {}
    # 11111 (22,) {}
    # end
面向对象方式(一般不用,了解即可):

8、多线程

1)计算密集型多线程无用,如下示例:

    import threading
    v1 = [11,22,33] # +1
    v2 = [44,55,66] # +100

    def func(data,plus):
        for i in range(len(data)):
            data[i] = data[i] + plus

    t1 = threading.Thread(target=func,args=(v1,1))
    t1.start()

    t2 = threading.Thread(target=func,args=(v2,100))
    t2.start()

2)IO操作,多线程有用(IO操作不占用cpu),如“三、线程和进程”中创建多个线程的代码示例;

9、多线程的问题(加锁+释放锁) 

    import time
    import threading

    lock = threading.RLock()

    n = 10

    def task(i):
        print('这段代码不加锁',i)

        lock.acquire() # 加锁,此区域的代码同一时刻只能有一个线程执行
        global n
        print('当前线程',i,'读取到的n值为:',n)
        n = i
        time.sleep(1)
        print('当前线程',i,'修改n值为:',n)
        lock.release() # 释放锁

    for i in range(10):
        t = threading.Thread(target=task,args=(i,))
        t.start()

总结:

       1. 应用程序/进程/线程的关系? *****(面试题:进程/线程/协程的区别?)

             

       2. 为什么要创建线程?

              由于线程是cpu工作的最小单元,创建线程可以利用多核优势实现并行操作(Java/C#)。

              注意:线程是为了工作。

                    

       3. 为什么要创建进程?

              进程和进程之间做数据隔离(Java/C#)。

                    

              注意:进程是为了提供环境让线程工作。

                    

       4. Python

              a. Python中存在一个GIL锁    *****

                     - 造成:多线程无法利用多核优势。

                     - 解决:开多进程处理(浪费资源)

                     进程和线程的使用准则:

                            IO密集型:多线程

                            计算密集型:多进程

              b. 线程的创建

                     - Thread             *****

                     - MyThread

              c. 其他

                     - join                  *****

                     - setDaemon      *****

                     - setName           *****

                     - threading.current_thread()  *****

              d. 锁

                     - 获得

                     - 释放

免责声明:文章转载自《操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇云计算商家必争之地 推荐几款云平台STM32 串口采用DMA方式收发下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python--循环

__author__ = 'maioge'i = 1# while i <= 5 :# print('miaoge')# i += 1# while i <= 5 :# if i<=3 :# print('miaoge')# i+=1# continue# break# while i...

python(3)- 循环语句:从最内层跳出多层循环

跳出多层循环:三层循环,最里层直接跳出3层方法一: 在Python中,函数运行到return这一句就会停止,因此可以利用这一特性,将功能写成函数,终止多重循环 def work(): #定义函数 for i in range(5): print("i=", i)...

WPF用样式实现TextBox的虚拟提示效果

【版权声明】本文为博主原创,未经允许禁止用作商业用途,如有转载请注明出处。  话说好多软件和网站都能实现虚拟提示,好吧这个名词是我自己起的,因为我也不知道这么形容这个效果。   效果描述:在TextBox没有输入值之前显示灰色提示信息,当获得焦点时提示自动消失,如果没有编辑离开此控件则依然显示提示信息,直到输入值为止。   效果图:   这里我用到了一个...

elementUI的input框textarea设置大小(以及禁止改变大小)

<el-form-item label="备注" prop="desc"> <el-input type="textarea" :rows="12" v-model="ruleForm.desc" height=200px></el-input> </el-form-item> :默认rows="...

网页支付页面代码

<html xmlns:ns1="og" lang="zh" xmlns="http://www.w3.org/1999/xhtml" ns1:xmlns="http://ogp.me/ns#" class=" jsEnabled"><head><meta http-equiv="Content-Type" content="...

【STM32H7】第3章 ThreadX操作系统介绍

论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514 第3章   ThreadX操作系统介绍 本章节介绍 ThreadX 操作系统,让大家对 ThreadX 有一个整体的了解。 3.1 初学者重要提示 3.2 Express Logic公司介绍 3.3 ThreadX...