C语言多线程编程
C语言是一种支持多线程编程的语言,它通过线程来实现并发执行,可以大大提高程序的运行效率和响应速度。在本文中,我们将介绍 C语言中的多线程编程,包括线程的创建、同步、互斥、条件变量等方面。
下面是一个简单的线程创建示例代码:
需要注意的是,在使用 pthread 库时,main 函数必须调用 pthread_exit 函数来结束程序,否则可能会出现线程无法正常退出的情况。
在 C语言中,可以使用 pthread 库中的 pthread_mutex_init、pthread_mutex_lock、pthread_mutex_unlock、pthread_mutex_destroy 函数来实现互斥锁。其中,pthread_mutex_init 函数用于初始化互斥锁,pthread_mutex_lock 函数用于加锁,pthread_mutex_unlock 函数用于解锁,pthread_mutex_destroy 函数用于销毁互斥锁。
下面是一个使用互斥锁的示例代码:
在线程函数中,首先调用 pthread_mutex_lock 函数获得锁,然后对 counter 变量进行操作,最后调用 pthread_mutex_unlock 函数释放锁。在 main 函数中,使用 pthread_join 函数等待线程 tid1 和 tid2 执行完毕,然后销毁互斥锁并打印出 counter 的最终值。
在 C语言中,可以使用 pthread 库中的 pthread_cond_init、pthread_cond_wait、pthread_cond_signal、pthread_cond_broadcast、pthread_cond_destroy 函数来实现条件变量。
其中,pthread_cond_init 函数用于初始化条件变量,pthread_cond_wait 函数用于等待条件变量,pthread_cond_signal 函数用于唤醒等待条件变量的线程,pthread_cond_broadcast 函数用于唤醒所有等待条件变量的线程,pthread_cond_destroy 函数用于销毁条件变量。
下面是一个使用条件变量的示例代码:
线程的创建
在 C语言中,可以通过 pthread 库来创建线程。pthread 库是一个 POSIX 标准的线程库,可以在 Linux、Unix 等操作系统上使用。线程的创建需要用到 pthread_create 函数,它的原型如下:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);参数说明:
- thread:指向 pthread_t 类型的指针,用于存储新创建的线程的 ID;
- attr:指向 pthread_attr_t 类型的指针,用于设置线程的属性,一般可以设置为 NULL;
- start_routine:指向线程的函数指针,该函数用于执行新线程的任务;
- arg:传递给线程函数的参数。
下面是一个简单的线程创建示例代码:
#include <stdio.h> #include <pthread.h> void *thread_func(void *arg) { printf("This is a new thread!\n"); pthread_exit(NULL); } int main() { pthread_t tid; pthread_create(&tid, NULL, thread_func, NULL); printf("This is the main thread!\n"); pthread_exit(NULL); }运行结果:
This is the main thread!
This is a new thread!
需要注意的是,在使用 pthread 库时,main 函数必须调用 pthread_exit 函数来结束程序,否则可能会出现线程无法正常退出的情况。
线程的同步
在多线程编程中,由于多个线程同时执行,可能会出现资源竞争的情况。为了避免这种情况,需要对线程进行同步。在 C语言中,可以使用互斥锁、条件变量等机制来实现线程同步。1) 互斥锁
互斥锁是一种用于保护共享资源的锁,只有获得锁的线程才能访问共享资源。在 C语言中,可以使用 pthread 库中的 pthread_mutex_init、pthread_mutex_lock、pthread_mutex_unlock、pthread_mutex_destroy 函数来实现互斥锁。其中,pthread_mutex_init 函数用于初始化互斥锁,pthread_mutex_lock 函数用于加锁,pthread_mutex_unlock 函数用于解锁,pthread_mutex_destroy 函数用于销毁互斥锁。
下面是一个使用互斥锁的示例代码:
#include <stdio.h> #include <pthread.h> int counter = 0; pthread_mutex_t mutex; void *thread_func(void *arg) { int i; for (i = 0; i < 1000000; i++) { pthread_mutex_lock(&mutex); counter++; pthread_mutex_unlock(&mutex); } pthread_exit(NULL); } int main() { pthread_t tid1, tid2; pthread_mutex_init(&mutex, NULL); pthread_create(&tid1, NULL, thread_func, NULL); pthread_create(&tid2, NULL, thread_func, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_mutex_destroy(&mutex); printf("counter = %d\n", counter); pthread_exit(NULL); }运行结果:
counter = 2000000
可以看到,在 main 函数中创建了两个线程 tid1 和 tid2,它们的任务是分别对 counter 变量进行 1000000 次累加操作。由于 counter 变量是一个共享资源,因此需要使用互斥锁来保护它。在线程函数中,首先调用 pthread_mutex_lock 函数获得锁,然后对 counter 变量进行操作,最后调用 pthread_mutex_unlock 函数释放锁。在 main 函数中,使用 pthread_join 函数等待线程 tid1 和 tid2 执行完毕,然后销毁互斥锁并打印出 counter 的最终值。
2) 条件变量
条件变量是一种用于线程间通信的机制,可以用于实现线程的等待和唤醒操作。在 C语言中,可以使用 pthread 库中的 pthread_cond_init、pthread_cond_wait、pthread_cond_signal、pthread_cond_broadcast、pthread_cond_destroy 函数来实现条件变量。
其中,pthread_cond_init 函数用于初始化条件变量,pthread_cond_wait 函数用于等待条件变量,pthread_cond_signal 函数用于唤醒等待条件变量的线程,pthread_cond_broadcast 函数用于唤醒所有等待条件变量的线程,pthread_cond_destroy 函数用于销毁条件变量。
下面是一个使用条件变量的示例代码:
#include <stdio.h> #include <pthread.h> int buffer = 0; pthread_mutex_t mutex; pthread_cond_t cond; void *producer(void *arg) { int i; for (i = 0; i < 10; i++) { pthread_mutex_lock(&mutex); buffer++; printf("Producer produced %d\n", buffer); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); sleep(1); } pthread_exit(NULL); } void *consumer(void *arg) { int i; for (i = 0; i < 10; i++) { pthread_mutex_lock(&mutex); while (buffer == 0) { pthread_cond_wait(&cond, &mutex); } buffer--; printf("Consumer consumed %d\n", buffer); pthread_mutex_unlock(&mutex); sleep(1); } pthread_exit(NULL); } int main() { pthread_t tid1, tid2; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); pthread_create(&tid1, NULL, producer, NULL); pthread_create(&tid2, consumer, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); pthread_exit(NULL); }运行结果:
Producer produced 1
Consumer consumed 0
Producer produced 1
Consumer consumed 0
Producer produced 1
Consumer consumed 0
Producer produced 1
Consumer consumed 0
Producer produced 1
Consumer consumed 0
Producer produced 1
Consumer consumed 0
Producer produced 1
Consumer consumed 0
Producer produced 1
Consumer consumed 0
Producer produced 1
Consumer consumed 0
Producer produced 1
Consumer consumed 0