消费者生产者问题:使用python实现

举报
码乐 发表于 2023/12/28 09:00:36 2023/12/28
【摘要】 简介在前面我们了解了python的异步库,这里通过可重入锁在python的同步线程中实现了 对线程异步的操作, 一个可重入锁必须由获得它的线程来释放。 一旦一个线程获得了一个可重入锁,同一个线程可以再次获得它而不阻塞。而该线程每获得一次锁,就必须释放一次锁。 获取的锁都必须释放一次。 它获取一个信号,将内部计数器递减1。当调用没有参数时:如果内部计数器在进入时大于 0,则将其递减1并立...

简介

在前面我们了解了python的异步库,这里通过可重入锁在python的同步线程中实现了 对线程异步的操作, 一个可重入锁必须由获得它的线程来释放。 一旦一个线程获得了一个可重入锁,同一个线程可以再次获得它而不阻塞。

而该线程每获得一次锁,就必须释放一次锁。 获取的锁都必须释放一次。 它获取一个信号,将内部计数器递减1。

当调用没有参数时:如果内部计数器在进入时大于 0,则将其递减1并立即返回。
如果它是零则阻塞,等待其他线程调用release(),使其大于零。

这是以适当的互锁方式进行的,因此 如果多个acquisition()调用被阻塞,release()将正好唤醒其中一个唤醒它们中的一个。

实现可能会随机选择一个,所以被阻塞的线程被唤醒的顺序为 唤醒被阻塞线程的顺序不应该被依赖。

在这种情况下,没有在这种情况下没有返回值。
当调用阻塞设置为 "true "时,做与调用 "无参数 "时相同的事情。 不带参数的情况下做同样的事情,并返回true。

当调用时将阻塞设置为false时,不要阻塞。如果一个没有参数的调用会阻塞,立即返回false;

否则,做与无参数调用时相同的事情,并返回true。

当调用时的超时时间不是None,它将阻塞最多 超时秒。
如果在这个时间段内,获取没有成功完成时间间隔内没有成功完成,则返回false。 否则返回true。

1 同步存,异步取

1.1 python线程 同步存入和异步取出

使用 入口判断 代码执行 同步还是异步,producer 同步 存入

   def producer(q, n):
	    for i in range(n):
	        q.put(i)
	    q.put(None)

   q = Queuey(2)

启用线程同步存入

  Thread(target=producer, args=(q, 10)).start()
  time.sleep(1)

启用线程循环,异步取出

  loop.run_until_complete(aconsumer(q)) 

运行时的输出,可以看到由于同步线程和异步线程的不同操作 输出的无序的:

        put sync item: 0
        put sync item: 1
        put sync item: 2
	get async item
	Async Got: 0
	get async item
	put sync item: 3
	Async Got:put sync item:  14
	get async item
	Async Got: 
	put sync item: 2
	get async item
	5
	Async Got: put sync item: 3
	6
	get async item
	Async Got: put sync item: 4
	7
	get async item
	Async Got: put sync item: 5
	8
	get async item
	Async Got: put sync item: 6
	9
	get async item
	Async Got:put sync item:  7None

	get async item
	Async Got: 8
	get async item
	Async Got: 9 

1.2 同步存,异步取:go的简单例子

同步存入时需要注意,把channel的长度与调用者匹配

 func SyncPutin(n int) {
	AsyncQueue = make(chan int, n)
	for i := 0; i < n; i++ {
		AsyncQueue <- i
	}
  }

在消费时取出即可

	func Customer(n int) {
		wg.Add(1)
		go func() {
			var count int
			for {
				fmt.Println("get async item")
				if count >= n {
					wg.Done()
					os.Exit(1)
				}
				count += 1
				newOne := <-AsyncQueue
				fmt.Println("Async Got:", newOne)
			}
		}()
		wg.Wait()
	}

运行输出

        get async item
	Async Got: 0
	get async item
	Async Got: 1
	get async item
	Async Got: 2
	get async item
	Async Got: 3
	get async item
	Async Got: 4
	get async item
	Async Got: 5
	get async item
	Async Got: 6
	get async item
	Async Got: 7
	get async item
	Async Got: 8
	get async item
	Async Got: 9

2 python线程 异步存取

2.1 异步存入 和 异步取出

使用异步库的队列,存取先后顺序并不重要。 异步取 异步存

   from asyncio import Queue

    q = Queue()
    loop.create_task(aconsumer(q))  
    loop.run_until_complete(aproducer(q, 10))   

实际的输出

  python async_third.py

    Async Got: 0
	Async Got: 1
	Async Got: 2
	Async Got: 3
	Async Got: 4
	Async Got: 5
	Async Got: 6
	Async Got: 7
	Async Got: 8
	Async Got: 9

2.2 异步存取 go的简单例子

go 的异步存入使用 内置的匿名函数即可

  func PutsIn(n int) {
		go func() {
			for i := 0; i < n; i++ {
				AsyncQueue <- i
			} 
		}() 
	}

消费者保持不变

	func Customer(n int) {
		wg.Add(1)
		go func() {
			var count int
			for {
				fmt.Println("get async item")
				if count >= n {
					wg.Done()
					os.Exit(1)
				}
				count += 1
				newOne := <-AsyncQueue
				fmt.Println("Async Got:", newOne)
			}
		}()
		wg.Wait()
	}

运行查看输出

  go run main.go

    get async item
	Async Got: 0
	get async item
	Async Got: 1
	get async item
	Async Got: 2
	get async item
	Async Got: 3
	get async item
	Async Got: 4
	get async item
	Async Got: 5
	get async item
	Async Got: 6
	get async item
	Async Got: 7
	get async item
	Async Got: 8
	get async item
	Async Got: 9

2 小结

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方在切回来的时候,恢复先前保存的寄存器上下文和栈。

因此,协程能保留上一次调用时的状态 也就是说:

    	进入上一次离开时所处逻辑流的位置。
    	线程和进程的操作是由程序触发系统接口,最后执行者是系统
    	协程的操作执行子则是用户自身程序,goroutine也是协程

goroutine 是Golang语言中最经典的设计,也是其魅力所在,goroutine本质是协程 是实现并行计算的核心。

goroutine 使用方式非常简单,只需要使用go关键字即可启动一个协程并且它是处于异步方式运行的,你不需要等它运行完成以后再执行以后的代码。

通过go 关键字启动一个协程来运行函数。

    go func() {}()

groutine能拥有强大的并发实现是通过GPM调度模型实现。

使用go的特性与python的经典一般用法进行比较似乎不太公平,这里只做简单对比,了解其优点.

完整代码:

    https://github.com/hahamx/examples/blob/main/alg_practice/1_pys_async/asyncio_cmp.py
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。