当前位置: 首页 > news >正文

二十五、Gtk4-多线程分析

1 回顾

1.1 Gnome相关

首先回顾一下GLib,GObject,GIO,Gtk的不同,因为下面会涉及到这些概念里面的函数。

所有这些都是由Gnome项目开发的库,一般都用于Gnome环境相关的应用程序。

  • Gtk:GUI界面库。
  • GLib:是一个通用的、可移植的实用程序库,它提供了许多有用的数据类型、宏、类型转换、字符串实用程序、文件实用程序、主循环抽象等等。
    • GMainLoop
    • GMainContext
    • GThread
    • GAsyncQueue
  • GObject:又名GLib对象系统,对象库(最初用于C编程语言,它不是面向对象的,但由于出现了与许多其他语言的绑定)。最初是GLib的一部分。Gtk中积极使用的对象和Gtk中的许多对象(如Gtk Window)继承了基本的GObject类型。其实就是一个基类型系统。
  • GIO:是一个库,为通用I/O、网络、IPC、设置和其他高级应用程序功能提供了有用的类。
    • GApplication
    • GSettings
    • GTask

1.2 ps命令

#查看运行的程序pid(进程号)
ps aux | grep application(应用程序的名字)
# 查看线程中的进程 -T表示开启线程查看
ps -T -p PID
# 杀死进程
kill -9 PID(进程号)

在这里插入图片描述
第一个标注的地方是CPU和内存占用率,后面的943100是物理内存使用量,单位是k,此时kafka大约占用943M内存
请添加图片描述

程序中我编写了onvif线程和主线程(Gtk),GLib命名的id并不会在ps查询命令显示,只运行该软件大概占用90M内存空间。SPID表示线程ID。

1.3 top命令

# -H表示开启线程查看, -p指定进程ID
top -H -p PID

请添加图片描述

第二个vpf-app应该就是onvif线程

onvif_seek_thread = g_thread_new("vpf.application.onvfi", vpf_application_onvif_run, app);

参考4:对于top命令显示信息的描述非常详细

2 GTK 多线程

2.1 信号与回调函数

GObject对象的信号在那个线程发出,回调函数就是那个线程执行。(跟回调函数在那个线程连接无关)。

Signals get executed in the context they are emitted from. In which context the object is created or where connect() is called from doesn’t matter.

2.2 如何区别函数运行在那个线程

GLib中,线程是一个抽象的概念,不能获取ID,可以通过两种方法判断该函数运行在那一个线程。GThread结构体内容并不公有。(该结构是不透明的——它的任何字段都不能直接访问。)

  • 通过 g_thread_self () 获取GThread结构体地址
  • 通过 pthread_t id = pthread_self ()函数

请添加图片描述
(vpf-app:86269)××××,86269是进程ID,Gtk报致命错误,可能是由于其它线程操作了UI界面。我的错误是因为,onvif线程中操作GListStore,因为GListStore与UI界面GtkColumnView绑定着。

2.3 如何将GTK与线程一起使用?

参考:How do I use GTK with threads?
GTK要求所有GTK API调用都来自创建GtkApplication的同一个线程,或者调用gtk_init()(主线程)。

如果想在GTK应用程序中利用多线程,通常最好将长时间运行的任务发送到工作线程,然后在工作线程使用g_idle_add或者GAsyncQueue反馈结果给UI线程(主线程)。GIO提供了有用的工具GTask。

3 GLib

3.1 GThread

这是一个结构体(不是GObject对象),表示一个正在运行的线程。该结构体由g_thread_new()或g_thread_try_new()返回。通过调用g_thread_self()可以获得表示当前线程的GThread结构体。

GThread被引用,请参阅g_thread_ref()和g_thread_unref()。由它表示的线程在运行时持有一个引用,而g_thread_join()消耗它给出的引用,因此通常没有必要显式管理GThread引用。

该结构是不透明的——它的任何字段都不能直接访问。

通过线程锁、条件,可以实现控制工作线程运行,如果工作线程不需要长时间运行,只有UI操作的时候运行一会,使用GTask更理想。

/* UI线程 *///告诉界面,我要让工作线程执行任务了...
g_cond_signal (&onvif_seek_cond);
/* 工作线程 */
g_mutex_lock (&onvif_seek_lock);/*** 要先上锁,是因为g_cond_wait函数要先解锁(如果未上错,会出错),再进入阻塞,等待cond* 等到cond,然后上锁,执行代码* 这个线程不能进行数据添加,因为添加数据会刷新UI*/
g_cond_wait (&onvif_seek_cond, &onvif_seek_lock);
...
...
g_mutex_unlock (&onvif_seek_lock);

注意

如果同一个线程在没有释放锁的情况下尝试连续两次执行g_mutex_lock(),则会导致死锁。这是因为当线程在第一次调用g_mutex_lock()时获得了互斥锁,并且在第二次调用g_mutex_lock()之前未释放互斥锁。这样,在第二次调用g_mutex_lock()时,线程将一直等待互斥锁被释放,从而导致死锁。

因此,应该避免在同一线程中连续两次调用g_mutex_lock()函数而不释放锁。一种常见的做法是使用g_mutex_trylock()函数来尝试获取互斥锁,如果获取不到,则返回并立即执行其他操作,而不是一直等待锁被释放。另外,在释放锁之前,应该确保在互斥锁保护的临界区内执行的所有操作都已经完成。

3.2 GMainContext

通过把源事件添加到工作线程或者UI线程

3.3 GAsyncQueue

4 GIO

4.1 GTask

4.2 GSettings

参考1:Linux下查看某一进程所占用内存的方法
参考2:Linux上如何查看某个进程的线程
参考3:linux ps命令,查看某进程cpu和内存占用率情况
参考4:Linux命令之top命令查看服务器CPU与内存占用

http://www.lryc.cn/news/7883.html

相关文章:

  • JVM基础学习
  • ASML逆袭史:人、资金、技术,缺一不可
  • MongoDB 覆盖索引查询
  • Flink Checkpoint 中的Aligned Checkpoint 和 Unaligned Checkpoint
  • C++快速入门
  • ubuntu18.04 network有线网络图标缺失解决记录
  • java对象克隆和面向对象的设计原则
  • 传透式血氧仪设计方案
  • 让逆向工程师们头疼的代码混淆,就像永远也走不出的“浪浪山”
  • 【拓展】基于机器学习的心脏病预测方法(14)——心脏病数据集补充
  • 深度解读Webpack中的loader原理
  • 2023年全国最新二级建造师精选真题及答案
  • 为什么现代企业发展离不开CRM系统的助力
  • vb.net计算之.net core基础(1)-获取农历和天气
  • 设计模式之代理模式详解和应用
  • JavaScript HTML DOM 节点列表
  • 【音视频处理】码率、帧率越高越清晰?分辨率、像素、dpi之间是什么关系?码率的真实作用,I帧、B帧、P帧是什么
  • Java基础-认识注释、标识符关键字
  • 【C#】静态扩展方法
  • 医疗电子方案——血压计方案
  • 深度分析React源码中的合成事件
  • 17.微服务SpringCloud
  • Java基础面试题——JavaWeb专题
  • MySql数据库约束
  • TripleCross:一款功能强大的Linux eBPF安全研究工具
  • 2023最牛教程,手把手教你成为年薪30W的测试开发
  • “深度学习”学习日记。--ImageNet、VGG、ResNet
  • 关于APP下载量提升的技巧
  • 以“大数据”赋能产业链精准招商
  • 内存泄漏检测组件 -- hook