C 语言多线程编程:并发和同步
发布时间: 2024-01-07 06:06:15 阅读量: 35 订阅数: 23
# 1. 简介
## 1.1 C语言多线程编程概述
在计算机领域中,并行指的是同时执行多个任务或操作的能力。多线程编程是一种并发编程技术,它允许程序在同一时间内执行多个线程,从而提高程序的并行度和运行效率。
C语言作为一种低级语言,提供了丰富的函数和库来支持多线程编程。通过使用C语言的多线程库,开发者可以创建、管理和同步多个线程,实现复杂的并发逻辑。
## 1.2 并发和同步的概念
并发是指两个或多个任务在同一时间段内执行的能力。在多线程编程中,并发可以通过同时创建和执行多个线程来实现,每个线程可以执行独立的任务。
然而,并发会引发一些问题,例如多个线程同时访问共享资源可能导致数据竞争和不一致的结果。为了解决这些问题,需要使用同步机制来保护共享资源的访问。
同步是指多个线程按照一定顺序执行,保证线程间共享资源的正确访问和操作。常见的同步机制包括互斥锁、信号量和条件变量等,它们可以用来实现线程的互斥执行和线程间的通信。
接下来,我们将深入探讨多线程编程的基础知识和并发编程技术。
# 2. 多线程基础知识
多线程是指在同一进程中同时运行多个线程,可以显著提高程序的运行效率。在C语言中,可以使用多线程库来实现多线程编程,常见的库包括 pthread 等。接下来我们将介绍多线程的基础知识,包括线程的创建和结束,线程的同步和互斥。
### 2.1 线程的创建和结束
在 C 语言中,可以使用 pthread_create 函数来创建一个新线程,语法如下:
```c
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
```
其中,thread 用于存储新线程的标识符,attr 用于设置新线程的属性,start_routine 是一个指向函数的指针,arg 则是传递给 start_routine 函数的参数。下面是一个简单的示例:
```c
#include <stdio.h>
#include <pthread.h>
void *print_message_function(void *ptr) {
char *message;
message = (char *)ptr;
printf("%s \n", message);
}
int main() {
pthread_t thread1;
char *message1 = "Thread 1";
int iret1;
iret1 = pthread_create(&thread1, NULL, print_message_function, (void *)message1);
pthread_join(thread1, NULL); // 等待线程结束
return 0;
}
```
在上面的示例中,我们通过 pthread_create 创建了一个新线程,并将 print_message_function 作为新线程的执行函数,最后使用 pthread_join 来等待新线程结束。
### 2.2 线程的同步和互斥
线程的同步和互斥是多线程编程中的重要概念,用于避免多个线程对共享资源的竞争而导致的数据不一致等问题。在 C 语言中,可以使用互斥锁(mutex)来实现线程的同步和互斥。一般的使用方法如下:
```c
#include <stdio.h>
#include <pthread.h>
int counter = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *print_count(void *ptr) {
int i;
for (i = 0; i < 10; i++) {
pthread_mutex_lock(&mutex);
counter++;
printf("Counter value: %d\n", counter);
pthread_mutex_unlock(&mutex);
}
}
int main() {
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, print_count, NULL);
pthread_create(&thread2, NULL, print_count, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
```
在上面的示例中,我们使用了互斥锁来保护 counter 这个共享资源,确保每次只有一个线程可以访问并修改它,从而避免了竞争条件。
# 3. 并发编程技术
在多线程编程中,需要考虑并发和同步的问题,以确保线程之间能够正确地协同工作。下面我们将介绍一些常用的并发编程技术。
#### 3.1 互斥锁的使用
互斥锁是一种用于保护临界区的同步机制,防止多个线程同时访问共享资源而引起的数据竞争问题。下面是一个使用互斥锁的示例代码:
```python
import threading
# 定义一个共享的全局变量
shared_variable = 0
# 创建一个互斥锁
mutex = threading.Lock()
# 线程函数
def thread_function():
global shared_variable
for _ in range(100000):
# 获取互斥锁
mutex.acquire()
shared_variable += 1
# 释放互斥锁
mutex.release()
# 创建两个线程并启动
thread1 = threading.Thread(target=thread_function)
thread2 = threading.Thread(target=thread_function)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
# 打印最终的共享变量的值
print("Final value of shared_variable:", shared_variable)
```
在上面的示例中,我们使用了Python的`threading`模块实现了一个简单的并发程序。在线程函数中,通过获取和释放互斥锁来保护共享变量`shared_variable`的访问,确保线程安全。
通过运行以上代码,你会发现`shared_variable`的最终值是一个确定的结果,这就是互斥锁保证了多个线程对共享资源的安全访问。
**代码总结:** 互斥锁是一种重要的并发编程技术,通过它可以保护共享资源,避免数据竞争和线程安全问题。
**结果说明:** 运行示例代码后,`shared_variable`的最终值应为 200000。
#### 3.2 信号量的应用
信号量是一种用于控制对共享资源的访问的同步工具,它可以限制同时访问共享资源的线程数量。下面是一个使用信号量的示例代码:
```java
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
static Semaphore semaphore = new Semaphore(1); // 创建一个初始值为1的信号量
static class ThreadA extends Thread {
public void run() {
try {
semaphore.acquire(); // 获取信号量
System.out.println("Thread A is accessing the shared resource");
sleep(1000); // 模拟访问共享资源的时间
semaphore.release(); // 释放信号量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ThreadB extends Thread {
public void run() {
try {
semaphore.acquire(); // 获取信号量
System.out.println("Thread B is accessing the shared resource");
sleep(1000
```
0
0