互斥锁(mutex lock)

互斥锁

解决临界区最简单的工具就是互斥锁(mutex lock)
一个进程在进入临界区的时候获得锁(函数acquire)
在退出临界区时释放锁(函数release)

每个互斥锁都有一个布尔变量available
表示锁是否可用
如果可用, 调用acquire会成功, 且锁不再可用
直到锁被释放后(调用release函数)其他进程才可以再次获得该锁
在这里插入图片描述

acquire()或release()的执行必须是原子操作
故通常采用硬件机制来实现

互斥锁的主要缺点: 忙等待
即违反了让权等待原则
当有一个进程在临界区中, 则其他任何进程在进入临界区前必须循环调用acquire()
浪费了CPU资源, 尤其是对于单处理器CPU
多处理器时其他一个线程可用在一个处理器上等待,
其他线程可以由其他处理器处理

需要连续循环忙等的互斥锁, 又可称为自旋锁(spin lock)
如TSL,
Swap指令,
单标志法

注意

  1. 需忙等
    自旋锁忙等, 违法了让权等待, 浪费了处理器资源
    但这并不意味着一直占用处理器
    时间片用完了自然会下处理器
  2. 忙等代价一定大?
    等待期间不需要进行进程切换,
    多处理器系统,
    上锁的时间短, 上锁操作简单, 则等待代价很低
    而且等待期间有可能使用临界区的进程释放了临界区
    但对于单处理机,
    其等待期间只会执行该等待的进程, 无法执行其他进程
    也就导致了占用临界区的进程并没有被执行, 也就无法释放临界区
    那纯纯白等
    所以自旋锁一般使用于多处理器系统
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,这是一个关于生产者消费者问题的描述。以下是一个简单的实现,包含主程序、生产者进程和消费者进程: ```c #include <stdio.h> #include <pthread.h> #include <semaphore.h> #define BUFFER_SIZE 10 char buffer[BUFFER_SIZE]; int buffer_index; pthread_mutex_t mutex; sem_t full, empty; void *producer(void *arg) { while (1) { // 生成数据项 char item = 'A' + rand() % 26; // 若缓冲区满,等待信号量empty sem_wait(&empty); // 获取互斥锁mutex pthread_mutex_lock(&mutex); // 将数据项放入缓冲区 buffer[buffer_index++] = item; // 释放互斥锁mutex pthread_mutex_unlock(&mutex); // 发送信号量full sem_post(&full); } } void *consumer(void *arg) { while (1) { // 若缓冲区空,等待信号量full sem_wait(&full); // 获取互斥锁mutex pthread_mutex_lock(&mutex); // 取出缓冲区中的数据项 char item = buffer[--buffer_index]; // 释放互斥锁mutex pthread_mutex_unlock(&mutex); // 发送信号量empty sem_post(&empty); // 处理数据项 printf("Consumed item: %c\n", item); } } int main() { buffer_index = 0; // 初始化互斥量和信号量 pthread_mutex_init(&mutex, NULL); sem_init(&full, 0, 0); sem_init(&empty, 0, BUFFER_SIZE); // 创建消费者线程和生产者线程,启动线程 pthread_t producer_thread, consumer_thread; 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); sem_destroy(&full); sem_destroy(&empty); return 0; } ``` 这个程序中,我们首先定义了一个缓冲区数组和一个缓冲区索引变量,用于存放生产者生成的数据项。接着,我们定义了一个互斥量mutex和两个信号量full、empty,分别表示缓冲区是否满或空。 在生产者进程中,我们使用while循环不断生成数据项。如果缓冲区已满,使用sem_wait()函数等待信号量empty。获取互斥锁mutex后,将数据项放入缓冲区中,然后释放互斥锁mutex。最后,使用sem_post()函数发送信号量full,通知消费者进程可以从缓冲区中取出数据项了。 在消费者进程中,我们也使用while循环不断消费数据项。如果缓冲区为空,使用sem_wait()函数等待信号量full。获取互斥锁mutex后,从缓冲区中取出数据项,并将缓冲区索引减一。然后,释放互斥锁mutex,并使用sem_post()函数发送信号量empty,通知生产者进程可以向缓冲区中放入数据项了。最后,我们处理取出的数据项,并输出到控制台上。 在主程序中,我们首先初始化互斥量和信号量。然后,创建消费者线程和生产者线程,并启动线程。最后,使用pthread_join()函数等待子线程完成后,销毁互斥量和信号量。 希望我的回答能够解决你的问题!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BetterChinglish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值