동시 프로그래밍 요약 (2)

동시 프로그래밍 요약 (2)

세마포어

  • 세마포어는 실제로 잠금입니다.
  • 동시에 뮤텍스 하나의 스레드 만 사용할 수 있도록하고, 세마포어는 다중 스레드를 할 수 있습니다. 세마포어가 인스턴스화 될 때, 동시 스레드의 수를 정의하는 매개 변수를 전달할 수
  • 당신은 가이드가 필요 from threading import Semaphore

예 :

from threading import Semaphore, Lock
from threading import current_thread
from threading import Thread
import time

sm = Semaphore(5)  # 
mutex = Lock()  # 


def task():
    # mutex.acquire()
    sm.acquire()
    print(f'{current_thread().name}执行任务')
    time.sleep(1)
    sm.release()
    # mutex.release()


for line in range(20):
    t = Thread(target=task)
    t.start()
    
# 结果:
Thread-1执行任务  
Thread-2执行任务
Thread-3执行任务
Thread-4执行任务
Thread-5执行任务
 此处等待1秒  # 就是每个线程里的那个 time.sleep(1)
Thread-6执行任务
Thread-9执行任务
Thread-7执行任务
Thread-8执行任务
Thread-10执行任务
 此处等待1秒
Thread-11执行任务
Thread-14执行任务
Thread-12执行任务
Thread-13执行任务
Thread-15执行任务
 此处等待1秒
Thread-16执行任务
Thread-18执行任务
Thread-17执行任务
Thread-19执行任务
Thread-20执行任务
 此处等待1秒

두 이벤트

1. 이벤트는 무엇입니까

  • 그것은 스레딩하는 방법입니다. 스레드는 차단 및 차단 해제를 제어하는 ​​데 사용됩니다.

사용이 무엇 2. 이벤트

  • 스레드의 실행을 제어하는 ​​데 사용, 스레드는 실행의 다른 스레드들에 의해 제어됩니다.

3. 이벤트 방법

  • wait 이러한 코드는 스레드가 존재하는 경우, 당신은 영구 차단 상태가됩니다 발생합니다.

  • set이러한 코드는 스레드가 존재하는 경우, 모든 만날 wait오픈. 준비 상태로 이러한 원래 스레드.

예 :

def light():
    print('红灯亮...')
    time.sleep(5)
    # 应该开始发送信号,告诉其他线程准备执行
    e.set()  # 将car中的False ---> True
    print('绿灯亮...')

def car(name):
    print('正在等红灯....')
    # 让所有汽车任务进入阻塞态
    e.wait()  # False
    print(f'{name}正在加速漂移....')

# 让一个light线程任务 控制多个car线程任务
t = Thread(target=light)
t.start()

for line in range(10):
    t = Thread(target=car, args=(f'童子军jason{line}号', ))
    t.start()

셋째, 프로세스 스레드 풀 수영장

1. 프로세스 스레드 풀 수영장 무엇입니까

  • 프로세스 풀 및 스레드 풀은 현재의 프로그램을 제어하는 ​​데 사용되는 숫자 / 스레드를 생성하는 과정을 수 있습니다.

사용이 무엇 2. 프로세스 풀 및 스레드 풀

  • 수가 하드웨어 프로세스 / 스레드에 의해 허용 범위가되도록 만든

3.

  1. 도서관 안내 :from concurrent.futures import ProcessPoolExecutor

  2. 셀 프로세스 / 스레드 풀 오브젝트의 예는 : pool = ThreadPoolExecutor(n)n은 기입 시간으로부터 충전 할 수 있고, (N)의 충전 개구 CPU 번호를 기입하지 않고, 프로세스 / 쓰레드를 나타내는 것은 * 5 CPU의 개수를 제한하는 기본 제한을 프로세스 수, 기본 스레드 수를 나타낸다

  3. submit주소 (즉, 함수 이름)의 함수에 매개 변수 전달, 비동기 작업을 제출하는 것입니다.

  4. submit(任务函数地址).add_done_callback(回调函数的地址). 작업이 값을 반환 할 때이 함수는 콜백 함수에 의해 받았을 때. 콜백 같은 형상 파라미터로서 res, res하지 함수의 리턴 값의 작업. 하여 res.result()함수의 반환 값 작업을 얻을 수 있습니다.
  5. shutdown결국 그것은 아래로 프로세스 / 스레드와 비슷한 코드를 실행, 스레드 풀 작업을 할 것입니다 join효과

예 :

# 任务函数没有返回值时*************************
def task():
    print('线程任务开始了...')
    time.sleep(3)
    print('线程任务结束了...')

for line in range(5):
    pool.submit(task)
    
pool.shutdown()

print('hello')   
# 任务函数有返回值时**********************************

def task(res):
    # res == 1
    print('线程任务开始了...')
    time.sleep(1)
    print('线程任务结束了...')
    return 123

# 回调函数
def call_back(res):
    print(type(res))
    # 注意: 赋值操作不要与接收的res同名
    res2 = res.result()
    print(res2)

for line in range(5):
    pool.submit(task, 1).add_done_callback(call_back)

pool.shutdown()

print('hello')    

넷째, 코 루틴 (사용 하나 개의 스레드 만)

1. 프로세스 / 스레드 / 코 루틴 차이점

  • 프로세스 : 자원 단위
  • 스레드 : 구현 단위
  • 코 루틴 : 단일 스레드 동시성에서
  • 참고 : 코 루틴이 아닌 운영 체제의 개념, 그것은 인위적으로 단일 스레드 동시성을 허용하기 위해, 생성 된 이름입니다.

코 루틴 2. 효과

  • + 보존 스위칭 상태 : 멀티 채널 기술은 핵심
    • 동시에 메모리 멀티 채널 작업을 넣어
    • 멀티 채널 작업이 CPU에서 실행 켜 IO 또는 경험 CPU 시간은 전환 너무 깁니다
    • 전환 할 때 작업 진행 상황이 저장됩니다
  • 코 루틴

    • + 아날로그 시스템의 수동 조작에 의해 저장된 상태 전환 달성 "다중 채널 기술"

    • CPU, 멀티 프로세스 / 스레드와 같은 여러 작업으로 스레드를 보자.

    • 상태를 저장 + 여러 작업 사이에 앞뒤로 스레드 스위치를 만드는 것입니다
    • IO 집중적를 들어, IO 스위치 + 상태를 저장 충족
    • 연산 집약적를 들어, 토글 +는 상태를 저장합니다. 연산 집약적를 들어, 낮은 효율 코 루틴의 사용.

  • 장점 :

    IO를 많이 사용의 경우, 효율성을 향상시킬 수

  • 단점 :

    스위칭 보낸 뒤로 덜 효율적인 계산 집약적의 경우,

3. 코 루틴을 구현하는 방법

(1) 여기서, 계산 집약적

  • 사용 yield상태를 저장
  • 전환은 동시입니다

예 :

import time

def func1():
    while True:
        10000000+1
        yield

def func2():
    
    g = func1() # 启动生成器 ,g 为生成器对象
    for i in range(10000000):
        time.sleep(10)  # 模拟IO,yield并不会捕捉到并自动切换
        i+1
        next(g)

start = time.time()
func2()
stop = time.time()
print(stop-start)

(2) IO 집약적 인 경우

  • 타사 라이브러리를 가져 오려면 :from gevent import monkey,spawn , joinall

  • gevent그것은 우리가 IO 작업 및 스위치를 모니터링하는 데 도움이 될 수 있습니다 타사 라이브러리입니다

  • 사용 gevent+ IO, 보존의 스위칭 상태가 발생 단일 스레드를 달성하기 위해 목적입니다

  • monkey.patch_all() 모든 IO는 수신기에서 작동 할 수 있습니다
  • spawn 和 joinall 저장 상태 스위치가 구현 될 수있다 +

예 :

from gevent import monkey
monkey.patch_all()  # 可以监听该程序下所有的IO操作
import time
from gevent import spawn, joinall  # 用于做切换 + 保存状态

def func1():
    print('1')
    # IO操作
    time.sleep(1)

def func2():
    print('2')
    time.sleep(3)

def func3():
    print('3')
    time.sleep(5)
    
start_time = time.time()

s1 = spawn(func1)  # 传任务
s2 = spawn(func2)
s3 = spawn(func3)

# s2.join()  # 发送信号,相当于等待自己 (在单线程的情况下)
# s1.join()     
# s3.join()

# 必须传序列类型,如列表和元组
joinall([s1, s2, s3])

end_time = time.time()

print(end_time - start_time)

다섯째, 단일 스레드의 동시 서버 달성

예 :

# 客户端*************************************
import socket
import time
from threading import Thread, current_thread


def client():
    client = socket.socket()
    client.connect(
        ('127.0.0.1', 9527)
    )
    print('启动客户端...')
    number = 0
    while True:
        send_data = f'{current_thread().name} {number}'
        client.send(send_data.encode('utf-8'))
        data = client.recv(1024)
        print(data.decode('utf-8'))
        number += 1


# 模拟了300个用户并发去访问服务端
for i in range(300):
    t = Thread(target=client)
    t.start()

    
# 服务端*********************************

from gevent import monkey
monkey.patch_all()  # 检测IO

import socket
import time
from threading import Thread
from gevent import spawn

server = socket.socket()

server.bind(
    ('127.0.0.1', 9527)
)

server.listen(5)
print('启动服务端...')


# 线程任务,执行接收客户端消息与发送消息给客户端
def working(conn):
    while True:
        try:
            data = conn.recv(1024).decode('utf-8')
            if len(data) == 0:
                break
            print(data)
            # time.sleep(1)
            send_data = data.upper().encode('utf-8')
            conn.send(send_data)

        except Exception as e:
            print(e)
            break

    conn.close()


def server2():
    while True:
        conn, addr = server.accept()
        # print(addr)
        # t = Thread(target=working, args=(conn,))
        # t.start()
        spawn(working, conn)


if __name__ == '__main__':
    s1 = spawn(server2)
    s1.join()


여섯 동시 프로그래밍 모듈에서 발생

모듈 및 방법 1. 프로세스를 가져와야

from multiprocessing import Process , Lock , RLock , Queue , Semaphore , Event


# 分别用来:创建进程,创建互斥锁,创建递归锁,创建队列,创建信号量 ,创建事件

모듈 및 방법은 스레드 2를 가져와야

from threading import Thread , current_thread , Lock , RLock , queue , Semaphpre , Event


# 分别用来:创建线程,返回当前线程的信息 , 创建互斥锁,创建递归锁,创建队列,创建信号量 ,创建事件

3. 수영장과 풀의 프로세스 모듈 및 스레드의 방법은 수입한다

from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor


# 分别用来: 创建进程池 , 创建线程池

모듈 및 4 코 루틴을 가져 오는 방법

from gevent import monkey , spawn , joinall


# 分别用来 监听线程中的所有IO操作 , 调用定义的任务 , 让主线程等待所有调用的任务执行结束再结束

여섯, I의 오가지 / O 모델

1. I / O 모델을 차단

2. I / O 모델을 비 차단

3. 다중 I / O 모델

4. 구동 신호 I / O 모델

비동기 I / O 모델

추천

출처www.cnblogs.com/Mcoming/p/11734409.html