【Linux 线程与进程】线程的同步与资源管理策略技术

发布于:2025-05-01 ⋅ 阅读:(12) ⋅ 点赞:(0)

目录

一. 背景

二. 高效同步机制实现

1. ‌轻量级锁(自旋锁)与互斥锁‌

‌1.1 轻量级锁(自旋锁)‌:

‌1.2 互斥锁‌

2. ‌条件变量减少忙等待‌

二、优化阻塞处理的实现

1. ‌分离阻塞操作到独立线程‌

2. ‌信号量与异步 I/O 提升 CPU 利用率‌

‌2.1 信号量控制并发资源‌

‌2.2 异步 I/O 模型‌

三、策略总结


一. 背景

在多线程编程中,同步与资源管理是保证程序正确性和性能的核心问题。‌线程同步‌用于协调多个线程对共享资源的访问,而‌资源管理‌则确保资源(如内存、文件、网络连接)的合理分配与释放。本文通过实例详解常见同步机制与资源管理策略。

二. 高效同步机制实现

1. ‌轻量级锁(自旋锁)与互斥锁

‌1.1 轻量级锁(自旋锁)‌:

  • 适用场景‌:保护执行时间极短的临界区(如计数器递增、标志位修改。

  • 实现原理‌:通过 CAS(Compare-And-Swap)原子操作尝试获取锁,失败时自旋而非阻塞线程,避免上下文切换开销。

 示例‌(基于 GCC 原子操作模拟自旋锁):

#include <stdatomic.h>
#include <stdbool.h>

typedef struct {
    atomic_bool locked;
} spinlock_t;

void spinlock_init(spinlock_t* lock) {
    atomic_init(&lock->locked, false);
}

void spinlock_lock(spinlock_t* lock) {
    // 自旋直到成功获取锁
    while (atomic_exchange(&lock->locked, true)) {
        // 自旋等待(空循环)
    }
}

void spinlock_unlock(spinlock_t* lock) {
    atomic_store(&lock->locked, false);
}

// ------------------ 使用示例 ------------------
spinlock_t counter_lock;
int counter = 0;

void* thread_func(void* arg) {
    spinlock_lock(&counter_lock);
    counter++;  // 临界区操作
    spinlock_unlock(&counter_lock);
    return NULL;
}

‌1.2 互斥锁

  • 适用场景‌:临界区执行时间较长(如文件读写、数据库操作)。
  • 示例‌(POSIX 线程互斥锁):
#include<pthread.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int share_data = 0;

void *thread_func(void *arg)
{
	pthread_mutex_lock(&mutex);
    ...
	//TO DO;长耗时的操作如写入文件
	share_data += 10;
    ...

	pthread_mutex_unlock(&mutex);
	
	return NULL;
}

2. ‌条件变量减少忙等待

  • 作用‌:通过事件通知机制唤醒等待线程,避免 CPU 空转。

  • 典型场景‌:生产者-消费者模型中协调缓冲区状态。

  •  示例‌(生产者-消费者模型):

    #include <pthread.h>
    #include <stdbool.h>
    
    #define BUFFER_SIZE 5
    
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t cond_producer = PTHREAD_COND_INITIALIZER;
    pthread_cond_t cond_consumer = PTHREAD_COND_INITIALIZER;
    
    int count = 0;
    int buffer[BUFFER_SIZE];
    
    void *prouducer(void *arg)
    {
    	for(int i = 0; i < 10; i++)
    	{
    		pthread_mutex_lock(&mutex);
    		while(count == BUFFER_SIZE)
    		{
    			pthread_cond_wait(&cond_producer, &mutex);
    		}
    		
    		buffer[count++] = i;
    		
    		printf("produced:%d\n",i);
    		pthread_cond_signal(&cond_consumer);
    		pthread_mutex_unlock(&mutex);
    	}
    	
    	return NULL;
    }
    
    void *consumer(void *arg)
    {
    	for(int i=0,i<10;i++)
    	{
    		pthread_mutex_lock(&mutex);
    		while(count == 0)
    		{
    			pthread_cond_wait(&cond_consumer, &mutex);
    		}
    		
    		int item = buffer[--count];
    		
    		printf("consumer:%d\n",item);
    		pthread_cond_signal(&cond_proudcer);
    		pthread_mutex_unlock();
    	}
    	return NULL;
    }

二、优化阻塞处理的实现

1. ‌分离阻塞操作到独立线程

  • 原理‌:将阻塞 I/O 分配到独立线程,主线程继续处理非阻塞任务。

  • 示例‌(创建独立线程处理文件读取):

    #include <pthread.h>
    #include <stido.h>
    #include <unistd.h>
    
    void *file_write(void *arg)
    {
    	FILE *fp = NULL;
    	fp = fopen("data.txt", "r");
    	if (fp)
    	{
    		char buffer[1024];
    		fread(buffer, sizeof(buffer), fp);
    		printf("read=%s",buffer);
    		fclose(fp);
    	}
    	
    	return NULL;
    }
    
    int main(void)
    {
    	pthread_t tid;
    	pthread_create(&tid, NULL, file_write, NULL);
    	
    	printf("main task");
    	
    	pthread_join(tid,NULL);
    
    	return 0;
    }

2. ‌信号量与异步 I/O 提升 CPU 利用率

‌2.1 信号量控制并发资源

  • 用途‌:限制同时访问资源的线程数量(如数据库连接池)。

  • 示例‌(POSIX 信号量)

    #include<semaphore.h>
    #include<pthread.h>
    #include<stdio.h>
    
    #define MAX_CONNECT_CNT 3
    sem_t db_sem;
    
    void *db_process(void *arg)
    {
    	sem_wait(&db_sem);
    	printf("pthread:%ld\n", pthread_self());
    	sleep(1);
    	sem_post(&db_sem);
    	
    	return NULL;
    }
    
    int main(void)
    {
    	pthread_t tid[5];
    	sem_init(&db_sem, 0, MAX_CONNECT_CNT);
    	
    	for(int i = 0;i<5; i++) 
    	{
    		pthread_create(&tid[i], NULL, db_process, NULL);
    		pthread_join(tid[i],NULL)
    		sem_destory(&db_sem);
     	}
    	
    	return 0;
    }

‌2.2 异步 I/O 模型

  • 原理‌:通过非阻塞 I/O 和回调机制分离计算与阻塞操作。

  • 示例‌(Linux AIO 基本使用)

    #include <aio.h>
    #include <fcntl.h> 
    #include <unistd.h> 
    
    void aio_callback(sigval_t sigval)
    {
    	struct aiocb *req = (struct aiocb*)sigval.sival_ptr; 
    	printf("Async read completed: %s\n", (char*)req->aio_buf);
    }
    
    int main() 
    { 
    	char buffer[1024]; 
        struct aiocb req = {0}; 
    
        int fd = open("data.txt", O_RDONLY); 
    
    	req.aio_fildes = fd;
    	req.aio_buf = buffer; 
    	req.aio_nbytes = sizeof(buffer); 
    	req.aio_offset = 0; 
    	req.aio_sigevent.sigev_notify = SIGEV_THREAD; 
    	req.aio_sigevent.sigev_notify_function = aio_callback; 
    	req.aio_sigevent.sigev_value.sival_ptr = &req; 
        aio_read(&req); 
    	// 发起异步读操作 
    	// 主线程继续执行其他任务 
    	printf("Main thread processing...\n"); 
    
    	sleep(2); // 等待异步操作完成 close(fd);
    	return 0; 
    }

三、策略总结

场景 技术方案 核心实现
短期临界区保护 自旋锁(原子操作) atomic_compare_exchange
长耗时同步任务 互斥锁 + 条件变量 pthread_mutex_lock/pthread_cond_wait
高并发阻塞操作 独立线程池 + 信号量 pthread_create/sem_wait
非阻塞 I/O 分离 异步 I/O 模型 aio_read + 回调机制

通过合理选择同步机制和异步模型,可显著提升多线程程序的吞吐量与响应速度。


网站公告

今日签到

点亮在社区的每一天
去签到