文章目录
1、多线程的问题引入
多线程的最大的特点是资源的共享,但是,当多个线程同时去操作(同时去改变)一个临界资源时,会破坏临界资源。如利用多线程同时写一个文件:
#include <stdio.h>
#include <pthread.h>
#include <malloc.h>
const char filename[] = "hello";
void* thread(void *id){
int i = 0;
int num = *(int *)id;
// 写文件的操作
FILE *fp = fopen(filename, "a+");
int start = *((int *)id);
int end = start + 1;
setbuf(fp, NULL);// 设置缓冲区的大小
fprintf(stdout, "%d\n", start);
for (i = (start * 10); i < (end * 10); i ++){
fprintf(fp, "%d\t", i);
}
fprintf(fp, "\n");
fclose(fp);
return NULL;
}
int main(){
int i = 0;
int num_thread = 5;
pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);
int * id = (int *)malloc(sizeof(int) * num_thread);
for (i = 0; i < num_thread; i++){
id[i] = i;
if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){
printf("thread create failed!\n");
return 1;
}
}
for (i = 0; i < num_thread; i++){
pthread_join(pt[i], NULL);
}
// 释放资源
free(pt);
free(id);
return 0;
}
执行以上的代码,我们会发现,得到的结果是混乱的,出现上述的最主要的原因是,我们在编写多线程代码的过程中,每一个线程都尝试去写同一个文件,这样便出现了上述的问题,这便是共享资源的同步问题,在Linux编程中,线程同步的处理方法包括:信号量,互斥锁和条件变量
2、互斥锁
互斥锁是通过锁的机制来实现线程间的同步问题。互斥锁的基本流程为:
1、初始化一个互斥锁:
pthread_mutex_init()
2、加锁:
pthread_mutex_lock() 或
pthread_mutex_trylock()
3、解锁:
pthread_mutex_unlock()
4、注销互斥锁:
pthread_mutex_destory()
5、pthread_mutex_lock()和pthread_mutex_trylock()区别
其中,在加锁过程中,pthread_mutex_lock()函数和pthread_mutex_trylock()函数的过程略有不同:
1、当使用pthread_mutex_lock()函数进行加锁时,若此时已经被锁,则尝试加锁的线程会被阻塞,直到互斥锁被其他线程释放,当pthread_mutex_lock()函数有返回值时,说明加锁成功;
2、而使用pthread_mutex_trylock()函数进行加锁时,若此时已经被锁,则会返回EBUSY的错误码。
6、解锁要满足的条件:
1、解锁前,互斥锁必须处于锁定状态;
2、必须由加锁的线程进行解锁。
当互斥锁使用完成后,必须进行清除。
扫描二维码关注公众号,回复:
8877222 查看本文章
有了以上的准备,我们重新实现上述的多线程写操作,其实现代码如下所示:
#include <stdio.h>
#include <pthread.h>
#include <malloc.h>
pthread_mutex_t mutex;
const char filename[] = "hello";
void* thread(void *id){
int i = 0;
// 加锁
int num = *(int *)id;
if (pthread_mutex_lock(&mutex) != 0){
fprintf(stdout, "lock error!\n");
}
// 写文件的操作
FILE *fp = fopen(filename, "a+");
int start = *((int *)id);
int end = start + 1;
setbuf(fp, NULL);// 设置缓冲区的大小
fprintf(stdout, "%d\n", start);
for (i = (start * 10); i < (end * 10); i ++){
fprintf(fp, "%d\t", i);
}
fprintf(fp, "\n");
fclose(fp);
// 解锁
pthread_mutex_unlock(&mutex);
return NULL;
}
int main(){
int i = 0;
int num_thread = 5;
pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);
int * id = (int *)malloc(sizeof(int) * num_thread);
// 初始化互斥锁
if (pthread_mutex_init(&mutex, NULL) != 0){
// 互斥锁初始化失败
free(pt);
free(id);
return 1;
}
for (i = 0; i < num_thread; i++){
id[i] = i;
if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){
printf("thread create failed!\n");
return 1;
}
}
for (i = 0; i < num_thread; i++){
pthread_join(pt[i], NULL);
}
pthread_mutex_destroy(&mutex);
// 释放资源
free(pt);
free(id);
return 0;
}