操作系统/应用程序, 操作中的"并发", 其他语言线程、进程, Python中线程和进程(GIL锁:全局解释器锁), Python线程编写+锁

一. 操作系统/应用程序

    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, args=(12,))
t.start()

print('end')

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

    总结:

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

Python多线程情况下:
    - 计算密集型操作:效率低。(GIL锁)
    - IO操作: 效率高

Python多进程的情况下:
    - 计算密集型操作:效率高(浪费资源)。 不得已而为之。
    - IO操作: 效率高 (浪费资源)。

写Python时:
    IO密集型用多线程: 文件/输入输出/socket网络通信
    计算密集型用多进程。

扩展:
    Java多线程情况下:
        - 计算密集型操作:效率高。
        - IO操作: 效率高
    Python多进程的情况下:
        - 计算密集型操作:效率高(浪费资源)。
        - IO操作: 效率高 浪费资源)。

 

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

    默认GIL锁在执行100个cpu指令(过期时间)。# v = sys.getcheckinterval()


五. Python线程编写

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

 

###################### 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()

 

# ################# 锁 ###################
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()

 

为什么要创建线程?
    由于线程是cpu工作的最小单元,创建线程可以利用多核优势实现并行操作(Java/C#)。
    线程是为了工作。
    
为什么要创建进程?
    进程和进程之间做数据隔离(Java/C#)。
    进程是为了提供环境让线程工作。

Python
    多线程无法利用多核优势。
    开多进程处理(浪费资源)
    IO密集型:多线程
    计算密集型:多进程

posted @ 2018-09-10 19:41  NachoLau  阅读(203)  评论(0编辑  收藏  举报