操作系统/应用程序、操作中的“并发”、线程和进程的区别,线程

 

 

并发编程前言:

      1、网络应用

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

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

           3)socketserver 源码-并发编程

      2、运维领域

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

一、操作系统/应用程序

a、硬件

       - 硬盘

       - CPU

       - 主板

       - 显卡

       - 内存

       - 电源

       . . . . . .

b、装系统(软件)

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

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

       - QQ

       - 百度云

       - pycharm

       . . . . . .

二、并行与并发

  

并发:是伪并行,即看起来是同时运行。单个cpu+多道技术就可以实现并发,(并行也属于并发)

 单cpu,多进程并发举例

 

  并行:并行:同时运行,只有具备多个cpu才能实现并行

 多个cpu、多进程并行举例

 

三、线程和进程

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

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

 

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

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

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

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

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

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

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

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

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

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

 线程和进程的效率对比:线程的效率非常高,并且线程开启不需要消耗什么资源

 线程的创建

   第一中创建方式:

threading四ruai顶      Thread死ruai的

import time
from threading import Thread
from multiprocessing import Process
def func(n):
    print(n)

if __name__ == '__main__':
    # t = Thread(target=func,args=('我是线程',))
    # t.start() #速度非常快
    p = Process(target=func,args=('我是进程',))
    p.start()
    print('主线程结束') 

  第二种创建方式: 函数继承Thread

class MyThread(Thread):

    def run(self):
        print('sb明杰')

if __name__ == '__main__':
    t = MyThread()
    t.start()
    print('主线程结束')

  

同一进程下,线程是资源共享的

import time
from threading import Thread
from multiprocessing import Process

num = 100
def func():
    global num
    num = 0

if __name__ == '__main__':
    t = Thread(target=func,)
    t.start()
    t.join()
    print(num)

  

 线程资源共享数据不安全,通过锁来解决数据不安全的问题,线程模块里面引入的锁

锁(同步锁\互斥锁):保证数据安全,但是牺牲了效率,同步执行锁内的代码

import time
from threading import Thread,Lock          Lock(拉客)
num = 100
def func(t_lock):
    global num
    # num -= 1
    t_lock.acquire()
    mid = num
    mid = mid - 1
    time.sleep(0.0001)
    num = mid
    t_lock.release()
if __name__ == '__main__':
    t_lock = Lock() #锁对象(同步锁,互斥锁)
    t_list = []
    for i in range(10):
        t = Thread(target=func,args=(t_lock,))
        t.start()
        t_list.append(t)
    [tt.join() for tt in t_list]

    print('主线程>>>',num)  

 解决死锁线程,用递归锁

互相抢到了对方的需要的锁,导致双方相互等待,程序没法进行

import time
from threading import Thread,Lock,RLock  #递归锁

class MyThread(Thread):

    def __init__(self,lockA,lockB):
        super().__init__()
        self.lockA = lockA
        self.lockB = lockB

    def run(self):
        self.f1()
        self.f2()
    def f1(self):

        self.lockA.acquire()
        print('我拿了A锁')

        self.lockB.acquire()
        print('我是一个很好的客户!')
        self.lockB.release()

        self.lockA.release()

    def f2(self):
        self.lockB.acquire()
        time.sleep(0.1)
        print('我拿到了B锁')
        self.lockA.acquire()
        print('我是一名合格的技师')
        self.lockA.release()

        self.lockB.release()


if __name__ == '__main__':
    # lockA = Lock()
    # lockB = Lock()
    # lockA = lockB = Lock() #不要这么写,别自己玩自己,锁自己
    lockA = lockB = RLock()

    t1 = MyThread(lockA,lockB)
    t1.start()

    t2 = MyThread(lockA,lockB)
    t2.start()

    print('我是经理')  

 线程进程效率对比

 

import time
from threading import Thread
from multiprocessing import Process

def func(n):
    num = 0
    for n1 in range(n):
        num += n1
    print('num',num)
if __name__ == '__main__':
    t_s_t = time.time()
    t_list = []
    for i in range(10):
        t = Thread(target=func,args=(10,))
        t.start() #速度非常快
        t_list.append(t)
    [tt.join() for tt in t_list]
    t_e_t = time.time()
    t_dif_t = t_e_t - t_s_t  #获取了线程的执行时间

    p_s_t = time.time() #开始时间
    p_list = []
    for ii in range(10):
        p = Process(target=func,args=(10,))
        p.start()
        p_list.append(p)
    [pp.join() for pp in p_list]
    p_e_t = time.time() #结束时间
    p_dif_t = p_e_t - p_s_t #时间差

    print('线程>>>>',t_dif_t)
    print('进程....',p_dif_t)
    print('主线程结束')  

 信号量

   信号量:控制同时能够进入锁内去执行代码的线程数量(进程数量),维护了一个计数器,刚开始创建信号量的时候假如设置的是4个房间,进入一次acquire就加一,出来一次就减一,如果计数器为0的时候,才可以继续抢钥匙,这样其他任务等待,这样的话,其他任务都是同步的状态,而进入acquire里面去执行的那四个任务是异步执行的

import time
from threading import Thread, Semaphore

def func1(s):
    s.acquire()
    time.sleep(1)
    print('大宝剑!!!')
    s.release()

if __name__ == '__main__':
    s = Semaphore(4)
    for i in range(10):
        t = Thread(target=func1,args=(s,))
        t.start() 

 主线程等待子线程的原因

 

import time
from threading import Thread
from multiprocessing import Process

def func(n):
    time.sleep(5)
    print(n)


if __name__ == '__main__':
    # 主线程等待的是子线程的任务全部执行完毕
    t = Thread(target=func, args=('我是子线程',))
    t.start()  # 速度非常快

    # 主进程等待的是给子进程收尸
    # p = Process(target=func,args=('我是子进程',))
    # p.start()
    # print('主进程结束!!')
    print('主线程结束')

守护线程 

  主线程等待所有非守护进程的结束才结束,主线程的代码运行结束,还要等待守护线的执行完毕,这个过程中守护线程还存在

守护进程

  主进程代码结束程序并没有结束,并且主进程还存在,进程等待其他的子进程执行结束以后,为子进程收尸,注意一个问题:主进程的代码运行结束守护进程跟着结束,

代码如下

 

import time
from threading import Thread
from multiprocessing import Process

def func1(n):
    time.sleep(5)
    print(n)
def func2(n):
    time.sleep(3)
    print(n)

if __name__ == '__main__':
    # 进程
    p1 = Process(target=func1,args=('我是子进程1号',))
    p1.daemon = True  #设置守护,在start之前加
    p1.start()
    p2 = Process(target=func2, args=('我是子进程2号',))
    p2.start()

    t1 = Thread(target=func1, args=('我是子xiancheng1号',))
    t1.daemon = True
    t1.start()
    t2 = Thread(target=func2, args=('我是子xiancheng2号',))
    t2.start()

    print('主进程结束!!')
    print('主线程结束')

 

线程的其他方法 1

from threading import Thread
import threading
import time
from multiprocessing import Process
import os

def work():
    import time
    time.sleep(1)
    # print('子线程',threading.get_ident()) #2608

if __name__ == '__main__':
    #在主进程下开启线程
    t=Thread(target=work)    #死如唉的
    t.start()
            current_thread(扣的死如爱的)
    print(threading.current_thread())#主线程对象 #<_MainThread(MainThread, started 1376)>    
    print(threading.current_thread().getName()) #主线程名称 #MainThread
    print(threading.current_thread().ident) #主线程ID #1376
    print(threading.get_ident()) #主线程ID #1376

    time.sleep(3)
    print(threading.enumerate())  # 连同主线程在内有两个运行的线程,        enumerate枚举(额牛木蕊特)
    print(threading.active_count()) # 2                   active_count(啊可特康特)
    print('主线程/主进程')

事件:

from threading import Thread,Event    Event(一温特)

e = Event()  #e的状态有两种,False True,当事件对象的状态为False的时候,wait的地方会阻塞

e.set()  #将事件对象的状态改为True
e.clear() #将事件对象的状态改为Flase      clear(克雷尔)
print('在这里等待')
e.wait() #阻塞                wait(威特)
print('还没好!!')

  

线程队列

队列有三种模式

  先进先出:

import queue
q=queue.Queue()
q.put('first')
# q.put_nowait() #不等待
print(q.get())
q.get_nowait() #没有数据就报错,可以通过try来搞       脑为特

  先进后出:

import queue
q=queue.LifoQueue() #队列,类似于栈,栈我们提过吗,是不是先进后出的顺序啊
q.put('third')
print(q.get())

  优先级队列:

import queue

q=queue.PriorityQueue()
#put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
q.put((-10,'a'))
q.put((-5,'a'))  #负数也可以
q.put((20,'ws'))  #如果两个值的优先级一样,那么按照后面的值的acsii码顺序来排序,如果字符串第一个数元素相同,比较第二个元素的acsii码顺序
q.put((20,'wd'))
q.put((20,{'a':11})) #TypeError: unorderable types: dict() < dict() 不能是字典
q.put((20,('w',1)))  #优先级相同的两个数据,他们后面的值必须是相同的数据类型才能比较,可以是元祖,也是通过元素的ascii码顺序来排序

'''
结果(数字越小优先级越高,优先级高的优先出队):
'''  

线程池:

import time

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
from threading import current_thread

def func(n):
    time.sleep(1)
    # print(n,current_thread().ident)
    return n**2

if __name__ == '__main__': 
    t_p = ThreadPoolExecutor(max_workers = 4)        max_workers(马克思我K儿死)
    map_res = t_p.map(func,range(10)) #异步执行的,map自带join功能
    print(map_res)
    print([i for i in map_res])

  

回调函数:

import time
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
from threading import current_thread

def func(n):
    time.sleep(1)
    print(n,current_thread().getName())
    return n**2

def func2(n):
    print('>>>>>>>',n.result())

if __name__ == '__main__':
    t_p = ThreadPoolExecutor(max_workers = 4)
    for i in range(3):
        t_p.submit(func,i).add_done_callback(func2)    add_done_callback(俺的 当 考班可)

    print('主线程结束')  

线程池的一些其他方法: 

ThreadPoolExecutor(死日无爱的  噗奥  A克赛K特)

ProcessPoolExecutor(噗赛死  噗奥  A克赛K特)

import time
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
from threading import current_thread

def func(n):
    time.sleep(1)
    # print(n,current_thread().ident)
    return n**2
if __name__ == '__main__':
    t_p = ThreadPoolExecutor(max_workers = 4)
    t_res_list = []
    for i in range(10): 
        res_obj = t_p.submit(func,i)#异步提交了10个任务,submit(色卖特)
        t_res_list.append(res_obj)

    t_p.shutdown()  #close + join    shutdown(莎当)        close(可篓子)
    for e_res in t_res_list:
        print(e_res.result())#他和get一样  result(蕊造特) 

 多线程和多进程进行纯计算的效率

import time
from multiprocessing import Process
from threading import Thread

def func():
    num = 0
    for i in range(1,10000000):
        num += i

# def func():
#     time.sleep(2)
#     print('xxxxxxxx')

if __name__ == '__main__':
    p_s_t = time.time()
    p_list = []
    for i in range(10):
        p = Process(target=func,)
        p_list.append(p)
        p.start()
    [pp.join() for pp in p_list]
    p_e_t = time.time()
    p_dif_t = p_e_t - p_s_t

    t_s_t = time.time()
    t_list = []
    for i in range(10):
        t = Thread(target=func,)
        t_list.append(t)
        t.start()
    [tt.join() for tt in t_list]
    t_e_t = time.time()
    t_dif_t = t_e_t - t_s_t

    print('多进程执行的时间',p_dif_t)
    print('多线程执行的时间',t_dif_t)

'''
多进程执行的时间 4.5982630252838135
多线程执行的时间 8.339477062225342
'''
运算

GIL锁:

 

并发执行的效率(在没有IO的情况下,两个纯计算的任务 )

import time
def func1():
    num2 = 0
    for i in range(1000001):
        num2 += i
        yield
        # print('执行到下一个yield',current_thread().name)

def func2():
    g = func1()
    next(g)
    sum = 0
    for i in range(1000000):
        # g.send(i)
        sum += i
        next(g)
s_t = time.time()
func2()
print('协程的时间',time.time() - s_t)  

 串行执行的效率

def func1():
    num2 = 0
    for i in range(1000001):
        num2 += i
        # print('执行到下一个yield',current_thread().name)

def func2():
    sum = 0
    for i in range(1000000):
        sum = sum + i


s_t = time.time()
func1()
func2()
print('串行的时间',time.time() - s_t)

'''
协程的时间 0.319796085357666
串行的时间 0.14291739463806152
'''

  

 

posted @ 2018-10-26 15:30  咖啡·  阅读(784)  评论(0编辑  收藏  举报