时间:2023-05-29 来源:网络 人气:
在多线程编程中,线程同步是一项非常重要的技术。如果不合理地处理线程同步,会导致程序出现各种难以排查的问题。本文将介绍Linux下常用的3种线程同步方法,帮助读者写出更加稳定的多线程程序。
1.互斥锁(mutex)
互斥锁是最基本的一种线程同步方法。当一个线程需要访问共享资源时,先尝试获取互斥锁。如果该锁已经被其他线程持有,则当前线程会进入睡眠状态,等待锁被释放后再次尝试获取。互斥锁可以保证共享资源在任意时刻只能被一个线程访问。
下面是一个使用互斥锁实现线程同步的示例代码:
c
#include<pthread.h>
#include<stdio.h>
intshared_resource=0;
pthread_mutex_tmutex;
void*thread_func(void*arg){
inti;
for(i=0;i<1000000;i++){
pthread_mutex_lock(&mutex);
shared_resource++;
pthread_mutex_unlock(&mutex);
}
returnNULL;
}
intmain(){
pthread_tthread1,thread2;
pthread_mutex_init(&mutex,NULL);
pthread_create(&thread1,NULL,thread_func,NULL);
pthread_create(&thread2,NULL,thread_func,NULL);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
printf("shared_resource=%d\n",shared_resource);
pthread_mutex_destroy(&mutex);
return0;
}
该程序创建了两个线程,并共享一个变量shared_resource。线程函数thread_func会对该变量进行1000000次自增操作,由于这是一个共享资源,需要使用互斥锁进行保护。在线程函数中,先调用pthread_mutex_lock函数获取互斥锁,然后执行共享资源的访问和修改操作,最后调用pthread_mutex_unlock函数释放互斥锁。
2.条件变量(conditionvariable)
条件变量是一种高级的线程同步方法,它允许一个或多个线程等待特定条件的出现。当条件不满足时,线程可以进入睡眠状态等待条件的出现。当其他线程改变了共享资源的状态并满足了条件时,它会通过条件变量通知等待的线程。
下面是一个使用条件变量实现生产者-消费者模型的示例代码:
c
#include<pthread.h>
#include<stdio.h>
#defineBUF_SIZE10
intbuffer[BUF_SIZE];
intcount=0;
pthread_mutex_tmutex;
pthread_cond_tcond;
void*producer(void*arg){
inti;
for(i=0;i<1000000;i++){
pthread_mutex_lock(&mutex);
while(count==BUF_SIZE){
pthread_cond_wait(&cond,&mutex);
}
buffer[count++]=i;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
returnNULL;
}
void*consumer(void*arg){
inti,value;
for(i=0;i<1000000;i++){
pthread_mutex_lock(&mutex);
while(count==0){
pthread_cond_wait(&cond,&mutex);
}
value=buffer[--count];
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
printf("%d\n",value);
}
returnNULL;
}
intmain(){
pthread_tproducer_thread,consumer_thread;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&producer_thread,NULL,producer,NULL);
pthread_create(&consumer_thread,NULL,consumer,NULL);
pthread_join(producer_thread,NULL);
pthread_join(consumer_thread,NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return0;
}
该程序创建了两个线程,一个生产者线程和一个消费者线程。它们共享一个大小为10的缓冲区,生产者线程会不断地往缓冲区中写入数据,消费者线程会不断地从缓冲区中读取数据。由于缓冲区是一个共享资源,需要使用互斥锁进行保护。当缓冲区已满时,生产者线程会进入睡眠状态等待条件变量的出现,当缓冲区为空时,消费者线程也会进入睡眠状态等待条件变量的出现。当生产者线程往缓冲区中写入数据后,会通过条件变量通知消费者线程,当消费者线程从缓冲区中读取数据后,也会通过条件变量通知生产者线程。
3.读写锁(read-writelock)
读写锁是一种特殊的互斥锁,它允许多个线程同时读取共享资源,但只允许一个线程进行写操作。如果一个线程已经获得了读锁,则其他线程可以继续获取读锁,但不能获取写锁。如果一个线程已经获得了写锁,则其他线程既不能获取读锁也不能获取写锁。
下面是一个使用读写锁实现并发读取和写入的示例代码:
c
#include<pthread.h>
#include<stdio.h>
intshared_resource=0;
pthread_rwlock_trwlock;
void*reader(void*arg){
inti,value;
for(i=0;i<1000000;i++){
pthread_rwlock_rdlock(&rwlock);
value=shared_resource;
pthread_rwlock_unlock(&rwlock);
printf("reader%d:%d\n",(int)arg,value);
}
returnNULL;
}
void*writer(void*arg){
inti;
for(i=0;i<1000000;i++){
pthread_rwlock_wrlock(&rwlock);
shared_resource++;
pthread_rwlock_unlock(&rwlock);
}
returnNULL;
}
intmain(){
pthread_treader_thread1,reader_thread2,writer_thread;
pthread_rwlock_init(&rwlock,NULL);
pthread_create(&reader_thread1,NULL,reader,(void*)1);
pthread_create(&reader_thread2,NULL,reader,(void*)2);
pthread_create(&writer_thread,NULL,writer,NULL);
pthread_join(reader_thread1,NULL);
pthread_join(reader_thread2,NULL);
pthread_join(writer_thread,NULL);
printf("shared_resource=%d\n",shared_resource);
pthread_rwlock_destroy(&rwlock);
return0;
}
该程序创建了两个读线程和一个写线程,并共享一个变量shared_resource。读线程会不断地读取该变量的值并输出,写线程会不断地对该变量进行自增操作。由于读操作可以同时进行,而写操作只能单独进行,因此需要使用读写锁进行保护。在读线程中,调用pthread_rwlock_rdlock函数获取读锁,然后执行共享资源的访问操作,最后调用pthread_rwlock_unlock函数释放读锁。在写线程中,调用pthread_rwlock_wrlock函数获取写锁,然后执行共享资源的修改操作,最后调用pthread_rwlock_unlock函数释放写锁。
通过使用互斥锁、条件变量和读写锁等线程同步方法,可以帮助我们编写出更加稳定、高效的多线程程序。在实际开发中,需要根据具体情况选择合适的线程同步方法,并注意避免死锁和饥饿等问题。
tokenpocket钱包:https://cjge-manuscriptcentral.com/software/2978.html