面试题答案
一键面试结构体参数传递方式
- 传指针:在多线程环境下,传指针是较为合适的方式。传值会在函数调用时复制整个结构体,这不仅浪费内存和时间,而且多个线程操作的是不同副本,无法共享数据,违背需求。而传指针能让不同线程操作同一个结构体实例,实现数据共享。例如:
#include <pthread.h>
#include <stdio.h>
// 定义共享数据结构体
typedef struct {
int data;
// 其他共享数据成员
} SharedData;
// 线程函数,接受共享数据结构体指针
void* thread_func(void* arg) {
SharedData* shared = (SharedData*)arg;
// 对共享数据进行操作
shared->data++;
return NULL;
}
int main() {
pthread_t tid;
SharedData shared = {0};
pthread_create(&tid, NULL, thread_func, &shared);
pthread_join(tid, NULL);
printf("Final data: %d\n", shared.data);
return 0;
}
避免竞态条件的同步机制
- 互斥锁(Mutex):在访问共享结构体数据前加锁,访问完后解锁。这确保同一时间只有一个线程能访问共享数据,避免竞态条件。例如在上述代码基础上添加互斥锁:
#include <pthread.h>
#include <stdio.h>
// 定义共享数据结构体
typedef struct {
int data;
// 其他共享数据成员
pthread_mutex_t mutex;
} SharedData;
// 线程函数,接受共享数据结构体指针
void* thread_func(void* arg) {
SharedData* shared = (SharedData*)arg;
pthread_mutex_lock(&shared->mutex);
// 对共享数据进行操作
shared->data++;
pthread_mutex_unlock(&shared->mutex);
return NULL;
}
int main() {
pthread_t tid;
SharedData shared = {0, PTHREAD_MUTEX_INITIALIZER};
pthread_create(&tid, NULL, thread_func, &shared);
pthread_join(tid, NULL);
pthread_mutex_destroy(&shared->mutex);
printf("Final data: %d\n", shared.data);
return 0;
}
- 读写锁(Read - Write Lock):如果读操作远多于写操作,使用读写锁更高效。读操作可以同时进行,写操作则需要独占锁。例如:
#include <pthread.h>
#include <stdio.h>
// 定义共享数据结构体
typedef struct {
int data;
// 其他共享数据成员
pthread_rwlock_t rwlock;
} SharedData;
// 读线程函数,接受共享数据结构体指针
void* read_thread_func(void* arg) {
SharedData* shared = (SharedData*)arg;
pthread_rwlock_rdlock(&shared->rwlock);
// 进行读操作
printf("Read data: %d\n", shared->data);
pthread_rwlock_unlock(&shared->rwlock);
return NULL;
}
// 写线程函数,接受共享数据结构体指针
void* write_thread_func(void* arg) {
SharedData* shared = (SharedData*)arg;
pthread_rwlock_wrlock(&shared->rwlock);
// 进行写操作
shared->data++;
pthread_rwlock_unlock(&shared->rwlock);
return NULL;
}
int main() {
pthread_t read_tid, write_tid;
SharedData shared = {0, PTHREAD_RWLOCK_INITIALIZER};
pthread_create(&read_tid, NULL, read_thread_func, &shared);
pthread_create(&write_tid, NULL, write_thread_func, &shared);
pthread_join(read_tid, NULL);
pthread_join(write_tid, NULL);
pthread_rwlock_destroy(&shared->rwlock);
printf("Final data: %d\n", shared.data);
return 0;
}
不同平台兼容性问题及应对策略
- Linux平台:Linux提供了丰富的POSIX线程库(pthread),上述使用互斥锁和读写锁的方案在Linux下能很好运行。但要注意在不同Linux内核版本下,线程库的性能和一些特性可能有微小差异,需参考官方文档确保代码兼容性。
- Windows平台:Windows没有POSIX线程库原生支持,可使用Windows API中的临界区(Critical Section)实现类似互斥锁功能,使用SRW锁实现类似读写锁功能。例如临界区使用:
#include <windows.h>
#include <stdio.h>
// 定义共享数据结构体
typedef struct {
int data;
// 其他共享数据成员
CRITICAL_SECTION cs;
} SharedData;
// 线程函数,接受共享数据结构体指针
DWORD WINAPI thread_func(LPVOID arg) {
SharedData* shared = (SharedData*)arg;
EnterCriticalSection(&shared->cs);
// 对共享数据进行操作
shared->data++;
LeaveCriticalSection(&shared->cs);
return 0;
}
int main() {
HANDLE tid;
SharedData shared = {0};
InitializeCriticalSection(&shared.cs);
tid = CreateThread(NULL, 0, thread_func, &shared, 0, NULL);
WaitForSingleObject(tid, INFINITE);
DeleteCriticalSection(&shared.cs);
printf("Final data: %d\n", shared.data);
CloseHandle(tid);
return 0;
}
为提高跨平台兼容性,可以使用跨平台库如Boost.Thread,它提供了统一的线程和同步原语接口,屏蔽了不同平台差异。在代码中引入Boost.Thread库后,可使用其提供的mutex和shared_mutex等同步工具,编写跨平台的多线程代码。