Linux多线程应用程序--新手练习程序
程序员文章站
2022-06-19 10:59:31
...
涉及的内容:任务队列、自旋锁、信号处理、生产者-消费者
可以用这个程序练习一下gdb多线程调试,编译命令:make v=debug
// task_queue.c
#include "task_queue.h"
Q_NODE *q_head = NULL, *q_tail = NULL, *q_current = NULL;
pthread_spinlock_t queue_spinlock;
int g_param = 0;
static pthread_t pid_producer, pid_consumer;
int init_queue(){
q_head = (Q_NODE *)malloc(sizeof(Q_NODE));
if (q_head == NULL) {
printf("%s: %d: %s\n", __func__, __LINE__, "q_head init failed!");
return -1;
}
q_head->func = NULL;
q_head->next = NULL;
q_tail = q_head;
q_current = q_head->next;
return 0;
}
void destory_queue(){
printf("\nCtrl+C pressed!\n");
printf("pid_producer pthread_cancel result: %d\n", pthread_cancel(pid_producer));
printf("pid_consumer pthread_cancel result: %d\n", pthread_cancel(pid_consumer));
printf("pid_producer pthread_join result: %d\n", pthread_join(pid_producer, NULL));
printf("pid_consumer pthread_join result: %d\n", pthread_join(pid_consumer, NULL));
while (q_current != NULL){
q_current = q_current->next;
free(q_head->next);
q_head->next = q_current;
}
free(q_head);
exit(0);
}
void show_queue(){
static Q_NODE *q_iterator;
pthread_spin_lock(&queue_spinlock);
q_iterator = q_head->next;
for(int i = 1; q_iterator != NULL; i++){
printf("Node %d, param %d\n", i, *(int *)(q_iterator->param));
q_iterator = q_iterator->next;
}
pthread_spin_unlock(&queue_spinlock);
}
int main(){
if (init_queue()){
return -1;
}
pthread_spin_init(&queue_spinlock, PTHREAD_PROCESS_PRIVATE);
if (pthread_create(&pid_producer, NULL, producer, NULL)) {
printf("%s: %d: %s\n", __func__, __LINE__, "producer process init failed!");
return -2;
}
if (pthread_create(&pid_consumer, NULL, consumer, NULL)) {
printf("%s: %d: %s\n", __func__, __LINE__, "consumer process init failed!");
return -3;
}
signal(SIGINT, destory_queue);
for(;;){
show_queue();
sleep(1);
}
return 0;
}
// producer.c
#include "task_queue.h"
int task_show_param(void *param){
printf("%s: %d: %s %d\n", __func__, __LINE__, "In task_show_param: param = ", *(int *)param);
return *(int *)param;
}
int task_minus_param(void *param){
*(int *)param -= 5;
printf("%s: %d: %s %d\n", __func__, __LINE__, "In task_minus_param: param = ", *(int *)param);
return *(int *)param;
}
void *producer(void *param){
(void)param;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
for(; ; g_param++) {
pthread_spin_lock(&queue_spinlock);
q_tail->next = (Q_NODE *)malloc(sizeof(Q_NODE));
if (q_tail->next == NULL) {
printf("%s: %d: %s\n", __func__, __LINE__, "task produced failed!");
exit(-1);
}
q_tail = q_tail->next;
q_tail->next = NULL;
// assign task
if (g_param < 5) {
q_tail->func = task_show_param;
} else {
q_tail->func = task_minus_param;
}
q_tail->param = (void *)&g_param;
pthread_spin_unlock(&queue_spinlock);
printf("%s: %d: %s %d\n", __func__, __LINE__, "In producer: g_param = ", g_param);
pthread_testcancel();
sleep(1);
}
return NULL;
}
// consumer.c
#include "task_queue.h"
void *consumer(void *param){
(void)param;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
for(;;)
{
pthread_spin_lock(&queue_spinlock);
if (q_current != NULL){
q_current->func(q_current->param);
printf("%s: %d: %s %d\n", __func__, __LINE__, "In consumer: g_param = ", *(int *)q_current->param);
if (q_current != q_tail){
q_current = q_current->next;
free(q_head->next);
q_head->next = q_current;
} else{
free(q_head->next);
q_head->next = NULL;
q_current = q_head->next;
q_tail = q_head;
}
pthread_spin_unlock(&queue_spinlock);
sleep(1);
} else {
q_current = q_head->next;
pthread_spin_unlock(&queue_spinlock);
printf("%s: %d: %s\n", __func__, __LINE__, "In consumer: waiting for producer!");
sleep(1);
}
pthread_testcancel();
}
exit(0);
}
// task_queue.h
#ifndef TASK_QUEUQ_H
#define TASK_QUEUQ_H
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
typedef struct _NODE{
int (*func)(void *);
void *param;
struct _NODE *next;
}Q_NODE;
void *consumer(void *param);
void *producer(void *param);
extern Q_NODE *q_head, *q_tail, *q_current;
extern pthread_spinlock_t queue_spinlock;
extern int g_param;
#endif
# Makefile
objects = task_queue.o producer.o consumer.o
cflags = -lpthread
cc = gcc
ifeq ($(v), debug)
cflags += -Wall -g3 -O0 -fsanitize=address
endif
all: $(objects)
$(cc) *.c -o task_queue $(cflags)
consumer.o: task_queue.h
producer.o: task_queue.h
task_queue.o: task_queue.h
.PHONY: clean
clean:
rm -rf *.o task_queue
执行结果:
上一篇: JQuery是什么
推荐阅读
-
Linux下如何实现shell多线程编程以提高应用程序的响应
-
Linux kde中11个你不知道的应用程序
-
python3+PyQt5实现支持多线程的页面索引器应用程序
-
Linux中使用Crontab定时监测维护Tomcat应用程序的方法
-
Linux上也有10个流行的Windows应用程序
-
详解Win10 Bash/WSL调试Linux环境下的.NET Core应用程序
-
CentOS+Linux部署.NET Core应用程序
-
详解Linux中将应用程序打包为Snap软件包格式的方法
-
Linux应用程序使用写文件调试程序的方法
-
CrossOver Linux版如何安装已知应用程序?CrossOver Linux版安装已知应用程序教程