操作系统丶并发并行和线程

一丶操作系统

  1.什么是操作系统: 操作系统是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在"裸机"上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行.

  2.硬件:硬件是由许多不同功能的模块化的部件组合而成的,并在软件的配合下完成输入丶处理丶存储丶和输出等四个操作步骤.另外还可根据它们的不同功能分为5类.

    1.输出设备(显示器丶打印机丶音响等)

    2.输入设备(鼠标丶键盘丶摄像头等)

    3.中央处理器

    4.储存器(内存丶硬盘丶光盘丶U盘以及存储卡等)

    5.主板(在各个部件之间进行协调工作丶是一个重要的连接载体)

  3.软件:软件是一系列按照特定顺序组织的计算机数据和指令的集合.一般来讲软件被划分为系统软件丶应用软件和介于这两者之间的中间件.软件并不只是包括可以在计算机上运行的电脑程序,与这些电脑程序相关的文档一般也被认为是软件的一部分.简单的说软件就是程序加文档的集合体.

二丶并发和并行

  并行:并行是指两者同时执,比如有两条车道,在某一个时间点,两条车道都有车在跑:(资源够用,比如三个线程,四核的CPU)

  并发:并发是指资源有限的情况下,两者交替轮流使用资源,比如只有一条车道(单核CPU资源),那么就是A车先走,在某个时刻A车退出把车道让给B车走,B走会儿再让给A走,交替使用,目的是提高效率.

  并发和并行的区别:

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

    并发是从宏观上,在一个时间段上可以看出是同时执行的,比如一个服务器处理多个请求

  注意!!!!!

    早起单核CPU时候,对于进程也是微观上串行(站在CPU的角度),宏观上并行(站在人的角度看就是同时有很多程序在执行)

  同步:所谓同步就是一个任务的完成需要依赖另一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列.要么成功都成功,要么都失败,两个任务的状态可以保持一致.

  异步:所谓异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了,至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠的任务序列

  阻塞与非阻塞

    阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关.也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的

三丶线程

  进程是资源分配的最小单位,线程是CPU调度的最小单位,每一个进程中至少有一个线程

线程的基本使用:

def func(arg):
    print(arg)

t = threading.Thread(target=func,args=(11,))
t.start()

print(123)
#11
#123
View Code

主程序默认等子线程执行完毕再结束:

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)
# 123
# 3
# 9
View Code

主线程不再等,主线程终止则所有子线程终止

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)
#123
View Code

开发者可以控制主线程等待子线程(最多等待时间)

import time
def func(arg):
    time.sleep(1)
    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)
View Code

线程名称:

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)
View Code

线程本质:

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

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

面向对象版本的多线程

# 多线程方式: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')
View Code

在计算密集型时多线程无用

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
    print(data)
t1 = threading.Thread(target=func,args=(v1,1))
t1.start()

t2 = threading.Thread(target=func,args=(v2,100))
t2.start()
# [12, 23, 34]
# [144, 155, 166]
View Code

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

  总结:

    start: 现在准备就绪,等待CPU调度

    setName: 为线程设置名称

    getName: 获取线程名称

    setDaemon: 设置为后台线程或前台线程(默认),如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止.如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止.

    join: 逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义

    run: 线程被CPU调度后自动执行线程对象的run方法

    

  加锁:

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()
View Code
原文地址:https://www.cnblogs.com/qicun/p/9620937.html