Linux和windows进程同步与线程同步那些事儿(三): Linux线程同步详解示例
在Linux中,线程同步可以通过多种机制来实现,其中最常见的包括互斥锁(mutex)、条件变量(condition variable)和信号量(semaphore)。
1. 互斥锁(Mutex
):
互斥锁是最常用的线程同步机制,它可以确保在同一时间只有一个线程可以访问共享资源。
在Linux中,可以使用pthread_mutex_t类型的互斥锁来实现线程同步。
代码示例:
#include <stdio.h>
#include <pthread.h>
int global_variable = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* thread_function(void* arg) {
for (int i = 0; i < 1000; i++) {
// 加锁
pthread_mutex_lock(&mutex);
// 修改全局变量
global_variable++;
// 解锁
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main() {
pthread_t thread1, thread2;
// 初始化mutex
pthread_mutex_init(&mutex, NULL);
// 创建两个线程
pthread_create(&thread1, NULL, thread_function, NULL);
pthread_create(&thread2, NULL, thread_function, NULL);
// 等待线程结束
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// 销毁mutex
pthread_mutex_destroy(&mutex);
printf("Global variable value: %d\n", global_variable);
return 0;
}
2. 条件变量(Condition Variable
):
条件变量用于线程间的通信和同步,允许线程等待某个特定条件的发生。
在Linux中,可以使用pthread_cond_t类型的条件变量来实现线程同步。
条件变量是一种同步机制,它允许线程在满足特定条件之前等待,并在条件满足时被其他线程通知。
示例代码:演示如何使用条件变量来控制多线程修改全局变量的值:
#include <stdio.h>
#include <pthread.h>
int global_var = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* thread_function(void* arg)
{
int new_value = *(int*)arg;
pthread_mutex_lock(&mutex);
// 等待条件满足
while (global_var != 0)
{
pthread_cond_wait(&cond, &mutex);
}
// 修改全局变量的值
global_var = new_value;
printf("Thread %d has modified global_var to %d\n", pthread_self(), global_var);
// 通知其他线程条件已经满足
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main()
{
pthread_t thread1, thread2;
int value1 = 123, value2 = 456;
// 创建两个线程
pthread_create(&thread1, NULL, thread_function, &value1);
pthread_create(&thread2, NULL, thread_function, &value2);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("Final value of global_var is %d\n", global_var);
return 0;
}
在上面的代码中,有两个线程分别调用thread_function
函数。此函数接收一个整数参数作为新的全局变量值。线程首先获得互斥锁并进入临界区,然后使用pthread_cond_wait
函数等待条件满足。只有当全局变量global_var
的值为0时,线程才被允许修改这个变量的值。一旦满足这个条件,线程就会修改全局变量的值,并通过pthread_cond_broadcast
函数通知其他等待这个条件的线程。最后,线程释放互斥锁并退出。
在main
函数中,我们创建了两个线程并等待它们完成。然后,我们打印最终的全局变量值。
通过使用条件变量,我们可以确保全局变量只能在满足特定条件时被修改,从而避免竞态条件和数据竞争的问题。
请注意,上述代码只是一个示例,用于说明如何使用条件变量来控制多线程修改全局变量的值。在实际的应用中,您可能还需要考虑其他方面,如错误处理和性能优化等。
3. 信号量(Semaphore
):
信号量是一种经典的线程同步机制,它可以用于控制对共享资源的访问。
在Linux中,可以使用sem_t类型的信号量来实现线程同步。
在Linux下,我们可以使用信号量来实现对多线程修改全局变量的值的控制。信号量是一种用于进程间同步和互斥的机制,可以用来控制对共享资源的访问。
信号量可以分为二进制信号量
和计数信号量
。二进制信号量只能取0或1,用于互斥操作。计数信号量可以取多个非负整数值,用于同步操作。
下面是一个简单的示例代码,实现了两个线程对全局变量进行自增操作的互斥控制:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
int global_var = 0;
sem_t sem;
void* thread_func(void* arg) {
int i;
for (i = 0; i < 100000; i++) {
sem_wait(&sem); // 等待信号量,若为0则阻塞
global_var++;
sem_post(&sem); // 释放信号量,唤醒等待的线程
}
return NULL;
}
int main() {
pthread_t thread1, thread2;
sem_init(&sem, 0, 1); // 初始化信号量,初始值为1
pthread_create(&thread1, NULL, thread_func, NULL);
pthread_create(&thread2, NULL, thread_func, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
sem_destroy(&sem); // 销毁信号量
printf("Global variable value: %d\n", global_var);
return 0;
}
在上面的示例中,我们首先通过 sem_init
函数初始化了一个计数信号量 sem
,初始值为1。然后创建了两个线程,并通过 pthread_create
函数将其与 thread_func
函数绑定。thread_func
函数中通过 sem_wait
函数等待信号量,当信号量的值为0时则阻塞,否则减1并继续执行。在对全局变量进行自增操作后,通过 sem_post
函数释放信号量,唤醒等待的线程。最后,通过 sem_destroy
函数销毁信号量。
运行该程序,两个线程会对全局变量 global_var
进行自增操作,由于信号量的存在,每次只能有一个线程能够修改该变量,从而实现了对全局变量访问的互斥控制。最终输出的全局变量值应为 200000。
需要注意的是,信号量的使用需要谨慎,错误的使用可能导致死锁等问题。确保在必要的时候对信号量加锁和解锁,并根据实际需求选择合适的信号量类型。
这些线程同步机制都可以通过Linux提供的pthread
库来使用。在实际编程中,选择合适的线程同步机制取决于具体的应用场景和需求,以确保线程间的安全访问和协调。
拓展:
在 Linux 中编译依赖 pthread 库的程序,可以使用以下命令行表达式来编译:
gcc -o output_file source_file.c -lpthread
其中,output_file
是编译后生成的可执行文件的文件名,source_file.c
是需要编译的源代码文件的文件名。
选项 -lpthread
表示链接 pthread
库,将其加入到编译过程中。
如果源文件有多个,可以将它们一一列出来,例如:
gcc -o output_file source_file1.c source_file2.c -lpthread
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!