大家好,我是木荣。今天我们再次探讨Linux多线程编程中的重要概念,特别是同步和互斥机制。
在多任务操作系统中,同时运行的多个任务可能需要共享同一资源。为了确保同一时刻只有一个任务能够访问该资源,需要使用互斥锁来对其进行保护。互斥锁是一种简单的加锁机制,用于控制对共享资源的访问。它只有两种状态,即锁定(lock)和解锁(unlock)。
对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,直到锁被释放
原子性:互斥锁是一个原子操作,操作系统保证如果一个线程锁定了一个互斥锁,那么其他线程在同一时间不会成功锁定这个互斥锁唯一性:如果一个线程锁定了一个互斥锁,在它解除锁之前,其他线程不可以锁定这个互斥锁非忙等待:如果一个线程已经锁定了一个互斥锁,第二个线程又试图去锁定这个互斥锁,则第二个线程将被挂起且不占用任何CPU资源,直到第一个线程解除对这个互斥锁的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥锁#include
#include
#include
#include
#include
char *pTestBuf = nullptr; // 全局变量
/* 定义互斥锁 */
pthread_mutex_t mutex;
void *ThrTestMutex(void *p)
{
pthread_mutex_lock(&mutex); // 加锁
{
pTestBuf = (char*)p;
sleep(1);
}
pthread_mutex_unlock(&mutex); // 解锁
}
int main()
{
/* 初始化互斥量, 默认属性 */
pthread_mutex_init(&mutex, NULL);
/* 创建两个线程对共享资源访问 */
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, ThrTestMutex, (void *)"Thread1");
pthread_create(&tid2, NULL, ThrTestMutex, (void *)"Thread2");
/* 等待线程结束 */
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
/* 销毁互斥锁 */
pthread_mutex_destroy(&mutex);
return 0;
}
读模式下加锁状态、写模式加锁状态、不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁,即允许多个线程读但只允许一个线程写。#include int phtread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
#include /** 加读锁 */ int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); /** 加写锁 */ int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); /** 释放锁 */ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
#include
#include
#include
#include
#include
/* 定义读写锁 */
pthread_rwlock_t rwlock;
/* 定义共享资源变量 */
int g_nNum = 0;
/* 读操作 其他线程允许读操作 不允许写操作 */
void *fun1(void *arg)
{
while(1)
{
pthread_rwlock_rdlock(&rwlock);
{
printf("read thread 1 == %d\n", g_nNum);
}
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}
/* 读操作,其他线程允许读操作,不允许写操作 */
void *fun2(void *arg)
{
while(1)
{
pthread_rwlock_rdlock(&rwlock);
{
printf("read thread 2 == %d\n", g_nNum);
}
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}
/* 写操作,其它线程都不允许读或写操作 */
void *fun3(void *arg)
{
while(1)
{
pthread_rwlock_wrlock(&rwlock);
{
g_nNum++;
printf("write thread 1\n");
}
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}
/* 写操作,其它线程都不允许读或写操作 */
void *fun4(void *arg)
{
while(1)
{
pthread_rwlock_wrlock(&rwlock);
{
g_nNum++;
printf("write thread 2\n");
}
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}
int main(int arc, char *argv[])
{
pthread_t ThrId1, ThrId2, ThrId3, ThrId4;
pthread_rwlock_init(&rwlock, NULL); // 初始化一个读写锁
/* 创建测试线程 */
pthread_create(&ThrId1, NULL, fun1, NULL);
pthread_create(&ThrId2, NULL, fun2, NULL);
pthread_create(&ThrId3, NULL, fun3, NULL);
pthread_create(&ThrId4, NULL, fun4, NULL);
/* 等待线程结束,回收其资源 */
pthread_join(ThrId1, NULL);
pthread_join(ThrId2, NULL);
pthread_join(ThrId3, NULL);
pthread_join(ThrId4, NULL);
pthread_rwlock_destroy(&rwlock); // 销毁读写锁
return 0;
}
结果
pthread_mutex_lock()/pthread_mutex_unlock()中mutex换成spin,如:pthread_spin_init()
include/linux/spinlock_type.h。自旋锁的接口函数全部定义在include/linux/spinlock.h头文件中,实际使用时只需include<linux></linux>即可 include
spinlock_t lock; //定义自旋锁
spin_lock_init(&lock); //初始化自旋锁
spin_lock(&lock); //获得锁,如果没获得成功则一直等待
{
....... //处理临界资源
}
spin_unlock(&lock); //释放自旋锁
线程在改变条件状态之前先锁住互斥量。如果条件为假,线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程。如果两进程共享可读写的内存,条件变量可以被用来实现这两进程间的线程同步
#include
#include
#include
#include
pthread_cond_t taxicond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t taximutex = PTHREAD_MUTEX_INITIALIZER;
void *ThrFun1(void *name)
{
char *p = (char *)name;
// 加锁,把信号量加入队列,释放信号量
pthread_mutex_lock(&taximutex);
{
pthread_cond_wait(&taxicond, &taximutex);
}
pthread_mutex_unlock(&taximutex);
printf ("ThrFun1: %s now got a signal!\n", p);
pthread_exit(NULL);
}
void *ThrFun2(void *name)
{
char *p = (char *)name;
printf ("ThrFun2: %s cond signal.\n", p); // 发信号
pthread_cond_signal(&taxicond);
pthread_exit(NULL);
}
int main (int argc, char **argv)
{
pthread_t Thread1, Thread2;
pthread_attr_t threadattr;
pthread_attr_init(&threadattr); // 线程属性初始化
// 创建三个线程
pthread_create(&Thread1, &threadattr, ThrFun1, (void *)"Thread1");
sleep(1);
pthread_create(&Thread2, &threadattr, ThrFun2, (void *)"Thread2");
sleep(1);
pthread_join(Thread1, NULL);
pthread_join(Thread2, NULL);
return 0;
}
结果
pthread_mutex_lock(&taximutex);
{
while(value != wantValue)
{
pthread_cond_wait(&taxicond, &taximutex);
}
}
pthread_mutex_unlock(&taximutex);
#include // 初始化信号量 int sem_init(sem_t *sem, int pshared, unsigned int value); // 信号量P操作(减 1) int sem_wait(sem_t *sem); // 以非阻塞的方式来对信号量进行减1操作 int sem_trywait(sem_t *sem); // 信号量V操作(加 1) int sem_post(sem_t *sem); // 获取信号量的值 int sem_getvalue(sem_t *sem, int *sval); // 销毁信号量 int sem_destroy(sem_t *sem);
// 信号量用于同步实例
#include
#include
#include
#include
sem_t sem_g,sem_p; //定义两个信号量
char s8Test = 'a';
void *pthread_g(void *arg) //此线程改变字符的值
{
while(1)
{
sem_wait(&sem_g);
s8Test++;
sleep(2);
sem_post(&sem_p);
}
}
void *pthread_p(void *arg) //此线程打印字符的值
{
while(1)
{
sem_wait(&sem_p);
printf("%c",s8Test);
fflush(stdout);
sem_post(&sem_g);
}
}
int main(int argc, char *argv[])
{
pthread_t tid1,tid2;
sem_init(&sem_g, 0, 0); // 初始化信号量为0
sem_init(&sem_p, 0, 1); // 初始化信号量为1
pthread_create(&tid1, NULL, pthread_g, NULL);
pthread_create(&tid2, NULL, pthread_p, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
结果
以上就是详解Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号