news 2026/6/8 10:03:44

跟我一起学“仓颉”编程语言-线程通知之Monitor

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
跟我一起学“仓颉”编程语言-线程通知之Monitor

一、线程通信

线程通信指的是线程之间的数据交换和同步控制。线程通信的目的是确保线程能够安全、高效的贡献数据和协调执行。

条件变量是一种同步原语,用于在并发编程中协调线程间的执行顺序。条件变量通常与互斥锁配合使用,以确保对共享数据的安全访问和对待特定条件的有效检查。

等待条件:一个或多个线程可以在条件变量上等待,直到某个条件成立。每个条件变量对应一个条件等待队列。

通知操作:另一个线程可以在条件变量上发出通知(信号),以唤醒一个或所有等待该条件的线程。

package Study import std.sync.* // 创建线程通信 let monitor = Monitor() // 条件是否满足的标记 var flag = false main () { let future1 = spawn { // 确保线程2先获得锁 sleep(Duration.second) synchronized(monitor) { println("线程1已创建") flag = true // 调用notify函数通知线程2 monitor.notify() println("线程1执行结束") } } let future2 = spawn { synchronized(monitor) { println("线程2已创建") while (!flag) { // 调用wait函数等待线程1的通知 monitor.wait() } println("线程2执行结束") } } future1.get() future2.get() }

二、wait函数的调用放在特定条件的while循环中

package Study import std.sync.* // 创建线程通信 let monitor = Monitor() // 条件是否满足的标记 var flag = false main () { let future1 = spawn { // 确保线程2先获得锁 sleep(Duration.second) synchronized(monitor) { println("线程1已创建") // 调用notify函数通知线程2 monitor.notify() println("线程1执行结束") } } let future2 = spawn { synchronized(monitor) { println("线程2已创建") // 调用wait函数等待线程1的通知 monitor.wait() println("线程2执行结束") } } future1.get() future2.get() }

注意:以上代码虽然结果相同,但是线程2有可能被假唤醒(线程在没有收到通知的情况下,从等待状态意外醒来)。为了正确处理多线程通知,建议始终将wait函数的调用放在检查特定条件的while循环里。

当一个Monitor实例调用了wait函数,wait函数将完成如下步骤

1. 添加当前线程到该Monitor实例对应的条件等待队列中;

2. 阻塞当前线程,同时释放该Monitor实例的锁;

3. 等待其他线程通过同一个Monitor实例调用notify函数或notifyAll函数发送的通知或等待超时;

4. 当前线程被唤醒后,会自动尝试重新获得锁。如果获取锁成功,从wait函数的调用点继续执行同步代码块;如果获取锁失败,则当前线程被加入锁等待队列并被阻塞。

三、notify函数和notifyAll函数不会释放锁

在调用notify函数或notifyAll函数后,当前线程仍然有锁。

package Study import std.sync.* class ProducerConsumer { // 生产产品总数 let total: Int64 // 表示是否已经生产了产品且还未被消费 var flag: Bool = false let monitor = Monitor() init(count: Int64) { this.total = count } // 创建一个线程用于生产 func produce() { spawn { for (i in 1..=total) { synchronized(monitor) { while(this.flag) { // 等待消费者消费产品 monitor.wait() } // 生产产品 println("已生产产品编号: ${i}") this.flag = true // 通知消费者产品已生产 monitor.notify() } } } } // 创建一个线程用于消费 func consume() { spawn { for (i in 1..=total) { synchronized(monitor) { while(!this.flag) { // 等待生产者生产产品 monitor.wait() } // 消费产品 println("已消费产品编号: ${i}") this.flag = false // 通知生产者产品已消费 monitor.notify() } } } } } main () { let producerConsumer = ProducerConsumer(10) // 创建生产者 let producer = producerConsumer.produce() // 创建消费者 let consumer = producerConsumer.consume() producer.get() consumer.get() }

在多线程中,锁的获取顺序是由线程控制器控制,因此结果是不确定的。

package Study import std.sync.* class ProducerConsumer { // 生产产品总数 let total: Int64 // 表示是否已经生产了产品且还未被消费 var flag: Bool = false let monitor = Monitor() init(count: Int64) { this.total = count } // 创建一个线程用于生产 func produce() { spawn { synchronized(monitor) { for (i in 1..=total) { while(this.flag) { // 等待消费者消费产品 monitor.wait() } // 生产产品 println("已生产产品编号: ${i}") this.flag = true // 通知消费者产品已生产 monitor.notify() } } } } // 创建一个线程用于消费 func consume() { spawn { synchronized(monitor) { for (i in 1..=total) { while(!this.flag) { // 等待生产者生产产品 monitor.wait() } // 消费产品 println("已消费产品编号: ${i}") this.flag = false // 通知生产者产品已消费 monitor.notify() } } } } } main () { let producerConsumer = ProducerConsumer(10) // 创建生产者 let producer = producerConsumer.produce() // 创建消费者 let consumer = producerConsumer.consume() producer.get() consumer.get() }

注意:选择for-in循环内使用synchronized块还是synchronized块内使用for-in循环,根据实际情况而选择,总之,对于使用Monitor的场景,需要仔细控制何时进入等待状态以及何时唤醒其他线程。

四、小结

本章为大家详细的介绍了仓颉编程语言中线程通知之Monitor的内容,下一章,为大家带来线程通知之MultiConditionMonitor的内容。最后,创作不易,如果大家觉得我的文章对学习仓颉服务端开发有帮助的话,就动动小手,点个免费的赞吧!收到的赞越多,我的创作动力也会越大哦,谢谢大家🌹🌹🌹!!!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/8 10:03:40

跟我一起学“仓颉”编程语言-多线程协调之Semaphore

一、Semaphore信号量是一种用于管理对共享资源的控制的同步机制。信号量的核心就是一个计数器,它表示可用的资源数量。获取:当一个线程要访问一个共享资源时,他会调用获取操作,如果信号量计数器大于0,有资源可用&#…

作者头像 李华
网站建设 2026/6/8 9:55:15

时间序列建模实战:从平稳性检验到ARIMA与LSTM协同预测

1. 这不是“调个包就完事”的时间序列课:一个真实从业者带你从数据缝里抠出规律 你是不是也试过——下载一份股票收盘价CSV,照着网上教程把 pandas.read_csv() 、 model.fit() 、 model.predict() 三行代码跑通,结果画出来的预测曲线像…

作者头像 李华