day 32 操作系统、线程和进程(GIL锁)

一、操作系统/应用程序

a. 硬件 
    - 硬盘
    - CPU 
    - 主板 
    - 显卡
    - 内存
    - 电源
    ...
b. 装系统(软件)
    - 系统就是一个由程序员写出来软件,该软件用于控制计算机的硬件,让他们之间进行相互配合。
    
c. 安软件(安装应用程序)
    - QQ
    - 百度云
    - pycharm

二、并发和并行

并发,伪,由于执行速度特别快,人感觉不到停顿。
并行,真,创建10个人同时操作。

三、线程和进程

a. 单进程、单线程的应用程序
print('666')
最简单
b. 到底什么是线程?什么是进程?
  Python自己没有这玩意,Python中调用的操作系统的线程和进程。

c. 单进程、多线程的应用程序
  一个应用程序(软件),可以有多个进程(默认只有一个),一个进程中可以创建多个线程(默认一个)
import threading
print('666')

def func(arg):
    print(arg)
t = threading.Thread(target=func)
t.start()

print('end')
代码
d. 故事: Alex甄嬛西游传

  总结:

    1. 操作系统帮助开发者操作硬件。
    2. 程序员写好代码在操作系统上运行(依赖解释器)。

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:
    task()


"""
- 你写好代码
- 交给解释器运行: python s1.py 
- 解释器读取代码,再交给操作系统去执行,根据你的代码去选择创建多少个线程/进程去执行(单进程/单线程)。
- 操作系统调用硬件:硬盘、cpu、网卡....
"""
以前的你,写代码:
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锁)
        - IO操作: 效率高 
        
    Python多进程的情况下:
        - 计算密集型操作:效率高(浪费资源)。 不得已而为之。
        - IO操作: 效率高 (浪费资源)。
    
    以后写Python时:
        IO密集型用多线程: 文件/输入输出/socket网络通信
        计算密集型用多进程。
    
    
    扩展:
        Java多线程情况下:
            - 计算密集型操作:效率高。
            - IO操作: 效率高 
        Python多进程的情况下:
            - 计算密集型操作:效率高(浪费资源)。
            - IO操作: 效率高 浪费资源)。

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

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

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

五、python线程编写

# by luffycity.com
import threading

# #################### 1. 计算密集型多线程无用 ####################
# 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操作 多线程有用 ####################
# 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()
View Code
# by luffycity.com
import threading


# ###################### 1.线程的基本使用 #################
# def func(arg):
#     print(arg)
#
#
# t = threading.Thread(target=func,args=(11,))
# t.start()
#
#
# print(123)
# ###################### 2.主线程默认等子线程执行完毕 #################
# 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=(9,))
# t2.start()
#
# print(123)
# ###################### 3.主线程不再等,主线程终止则所有子线程终止 #################
# import time
# def func(arg):
#     time.sleep(2)
#     print(arg)
#
# t1 = threading.Thread(target=func,args=(3,))
# t1.setDaemon(True)
# t1.start()
#
# t2 = threading.Thread(target=func,args=(9,))
# t2.setDaemon(True)
# t2.start()
#
# print(123)

# ###################### 4.开发者可以控制主线程等待子线程(最多等待时间) #################
# import time
# def func(arg):
#     time.sleep(0.01)
#     print(arg)
#
# print('创建子线程t1')
# t1 = threading.Thread(target=func,args=(3,))
# t1.start()
# # 无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。
# # 有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。
# t1.join(2)
#
# print('创建子线程t2')
# t2 = threading.Thread(target=func,args=(9,))
# t2.start()
# t2.join(2) # 让主线程在这里等着,等到子线程t2执行完毕,才可以继续往下走。
#
# print(123)

# ###################### 4.线程名称 #################
# 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)

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


# ###################### 6.补充:面向对象版本的多线程 #################
# 多线程方式:1 (常见)
# def func(arg):
#     print(arg)
#
# t1 = threading.Thread(target=func,args=(11,))
# t1.start()

# 多线程方式:2
# class MyThread(threading.Thread):
#
#     def run(self):
#         print(11111,self._args,self._kwargs)
#
# t1 = MyThread(args=(11,))
# t1.start()
#
# t2 = MyThread(args=(22,))
# t2.start()

print('end')
线程的使用
# by luffycity.com
import threading


# ###################### 1.线程的基本使用 #################
# def func(arg):
#     print(arg)
#
#
# t = threading.Thread(target=func,args=(11,))
# t.start()
#
#
# print(123)
# ###################### 2.主线程默认等子线程执行完毕 #################
# 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=(9,))
# t2.start()
#
# print(123)
# ###################### 3.主线程不再等,主线程终止则所有子线程终止 #################
# import time
# def func(arg):
#     time.sleep(2)
#     print(arg)
#
# t1 = threading.Thread(target=func,args=(3,))
# t1.setDaemon(True)
# t1.start()
#
# t2 = threading.Thread(target=func,args=(9,))
# t2.setDaemon(True)
# t2.start()
#
# print(123)

# ###################### 4.开发者可以控制主线程等待子线程(最多等待时间) #################
# import time
# def func(arg):
#     time.sleep(0.01)
#     print(arg)
#
# print('创建子线程t1')
# t1 = threading.Thread(target=func,args=(3,))
# t1.start()
# # 无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。
# # 有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。
# t1.join(2)
#
# print('创建子线程t2')
# t2 = threading.Thread(target=func,args=(9,))
# t2.start()
# t2.join(2) # 让主线程在这里等着,等到子线程t2执行完毕,才可以继续往下走。
#
# print(123)

# ###################### 4.线程名称 #################
# 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)

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


# ###################### 6.补充:面向对象版本的多线程 #################
# 多线程方式:1 (常见)
# def func(arg):
#     print(arg)
#
# t1 = threading.Thread(target=func,args=(11,))
# t1.start()

# 多线程方式:2
# class MyThread(threading.Thread):
#
#     def run(self):
#         print(11111,self._args,self._kwargs)
#
# t1 = MyThread(args=(11,))
# t1.start()
#
# t2 = MyThread(args=(22,))
# t2.start()

print('end')
多线程
# by luffycity.com
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()
多线程问题

暂时忘记知识点

import sys

v1 = sys.getcheckinterval()
print(v1)
查看gil切换指令
总结:
1. 应用程序/进程/线程的关系? *****(面试题:进程/线程/协程的区别?)

2. 为什么要创建线程?
    由于线程是cpu工作的最小单元,创建线程可以利用多核优势实现并行操作(Java/C#)。
    注意:线程是为了工作。
    
3. 为什么要创建进程?
    进程和进程之间做数据隔离(Java/C#)。
    
    注意:进程是为了提供环境让线程工作。
    
4. Python
    a. Python中存在一个GIL锁。 *****
        - 造成:多线程无法利用多核优势。
        - 解决:开多进程处理(浪费资源)
        总结:
            IO密集型:多线程 
            计算密集型:多进程
    b. 线程的创建 
        - Thread         *****
        - MyThread 
    c. 其他 
        - join             *****
        - setDeanon        *****
        - setName        *****
        - threading.current_thread()    *****
    d. 锁
        - 获得 
        - 释放 
扫描二维码关注公众号,回复: 7758787 查看本文章

猜你喜欢

转载自www.cnblogs.com/xiaobai686/p/11802712.html