网络编程------死锁现象/线程队列/协程

死锁现象(了解)

死锁:
	# 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象
'''单进程和单线程不会出现死锁现象'''
# 哲学家吃面问题
import time
from threading import Thread, Lock, RLock

# noodle_lock = Lock()
# fork_lock = Lock()
noodle_lock = fork_lock = RLock()  # 递归锁,也叫可重入锁
# noodle_lock = RLock()
# fork_lock = RLock()

def eat1(name):
    noodle_lock.acquire()
    print('%s 抢到了面条' % name)
    fork_lock.acquire()
    print('%s 抢到了叉子' % name)
    print('%s 吃面' % name)
    fork_lock.release()
    noodle_lock.release()


def eat2(name):
    fork_lock.acquire()
    print('%s 抢到了叉子' % name)
    time.sleep(1)
    noodle_lock.acquire()
    print('%s 抢到了面条' % name)
    print('%s 吃面' % name)
    noodle_lock.release()
    fork_lock.release()


for name in ['哪吒', 'jack', 'tank']:
    t1 = Thread(target=eat1, args=(name,))
    t2 = Thread(target=eat2, args=(name,))
    t1.start()
    t2.start()

线程队列

"""
同一个进程下多个线程数据是共享的
为什么先同一个进程下还会去使用队列呢
因为队列是
    管道 + 锁
所以用队列还是为了保证数据的安全
"""

from multiprocessing import Queue
进程队列:Queue

import queue
线程队列:queue

"""
	进程Queue用于父进程与子进程(或同一父进程中多个子进程)间数据传递
    python自己的多个进程间交换数据或者与其他语言(如Java)进程queue就无能为力

    queue.Queue 的缺点是它的实现涉及到多个锁和条件变量,因此可能会影响性能和内存效率。
"""

线程队列有3种:
	1. 先进先出
    2. 先进后出
    3. 优先级队列
    
'''优先级队列'''
q = queue.PriorityQueue()
# put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
q.put((5, 'a'))  # 元组里面的第一个数字代表的是优先级,第二个元素是具体的数据
q.put((15, 'b'))
q.put((10, 'c'))

print(q.get())
print(q.get())
print(q.get())
'''
结果(数字越小优先级越高,优先级高的优先出队):
(10, 'b')
(20, 'a')
(30, 'c')
'''

进程池和线程池(掌握思路)

池:盛放更多个对象的,盛放更多的进程和线程

'''进程池和线程池都是提供的是异步调用,只需要往池子里丢任务,我们不需要等待结果,等池子里面的任务完成之后,内部做了一个回调,告诉我们执行后的结果!!!'''
# 进程池:
	提前创建一个池子,这个池子里面先创建号一怼进程,然后,只需要向池子里面丢任务就行.

# 线程池:
	提前创建一个池子,这个池子里面先创建号一怼线程,然后,只需要向池子里面丢任务就行.
创建池的目的:节省资源,防止内存被沾满的情况,另外就是也能提升效率,但是不能无限的开进程.


'''写个进程池来执行任务'''
def task(n, m,):
    return n + m


# res=task(1, 2)
# print(res)

def callback(res):
    print(res) # <Future at 0x14786aa45e0 state=finished returned int>
    print(res.result())  # 3
if __name__ == '__main__':
    # 1. 创建进程池
    p_pool = ProcessPoolExecutor(5)  # 创建一个池子,里面有5个进程

    # 2. 执行任务,只需要往池子里面丢任务
    # p_pool.submit(task, 1, 2)
    p_pool.submit(task, n=1, m=2).add_done_callback(callback)

线程池爬取网页

import requests
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor


def get_page(url):
    # requests.get('http://www.baidu.com')
    res = requests.get(url)  # 爬取网页
    name = url.rsplit('/')[-1] + '.html'  # www.baidu.com.html
    return {'name': name, 'text': res.content}


def call_back(fut):
    print(fut.result()['name'])
    with open(fut.result()['name'], 'wb') as f:
        f.write(fut.result()['text'])


if __name__ == '__main__':
    pool = ThreadPoolExecutor(5)
    urls = ['http://www.baidu.com', 'http://www.cnblogs.com', 'http://www.taobao.com']
    for url in urls:
        pool.submit(get_page, url).add_done_callback(call_back)

协程

进程:资源分配的最小单位
	
线程:CPU执行的最小单位

协程:
    # 协程的概念在操作系统中,压根不存在,操作系统中有的是进程和线程概念,他们两个都是有操作系统调度
    # 协程是有我们程序员意淫出来的,它也称作是用户态的轻量级线程. 用户态---->程序员
'''协程它是单线程下的并发.'''
# 并发:
	切换,保存状态
# 如何使用协程:
	本质:还是来回切换(程序级别切换)
'''要想使用协程,需要借助于第三方模块:gevent模块!!!'''
1. 需要下载和安装gevent模块
pip install gevent

协程实现高并发

服务端

#######################################服务端########################################
import socket
'''猴子补丁'''
from gevent import monkey;
monkey.patch_all()  # 检测IO
'''协程实现并发:其实是欺骗CPU的行为'''
# 1. 遇到io,2. 切换

'''并发:1, 遇到IO操作,会切换'''



from gevent import spawn


def talk(sock):
    while True:
        try:
            data = sock.recv(1024)
            if len(data) == 0: break
            print(data)
            sock.send(data + b'ly is handsome!')
        except ConnectionResetError as e:
            print(e)
            sock.close()
            break

from multiprocessing import Process
def servers():
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen()

    while True:
        sock, addr = server.accept()
        # p = Process(target=talk)
        # p.start()
        spawn(talk, sock)  ### 开销是非常小的


'''协程是单线程下的并发!!!'''
g1 = spawn(servers)  # 单线程下开着,,,,,单线程下的并发
g1.join()

客户端

from threading import Thread, current_thread
from socket import *


def client():
    client = socket(AF_INET, SOCK_STREAM)
    client.connect(('127.0.0.1', 8080))

    n = 0
    while True:
        msg = '%s say hello %s' % (current_thread().name, n)
        n += 1
        client.send(msg.encode('utf-8'))
        data = client.recv(1024)
        print(data.decode('utf-8'))


if __name__ == '__main__':
    for i in range(5000):
        t = Thread(target=client)
        t.start()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑猪去兜风z1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值