嵌入式技术
Hello、Hello大家好,我是木荣,今天我们继续来聊一聊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
即可include
线程在改变条件状态之前先锁住互斥量。如果条件为假,线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程。如果两进程共享可读写的内存,条件变量可以被用来实现这两进程间的线程同步
#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;
}
结果
好了,通过这篇文章希望对小伙伴们有所帮助,希望能更深刻的理解多线程编程中的知识。
全部0条评论
快来发表一下你的评论吧 !