Lecture 8 Mutex Locks(互斥锁)

1 临界区问题

临界区问题

  • 每个并发进程都有一段被称作临界区的代码,该过程可能正在更改公共变量、更新表、写入文件等。
  • 该系统的重要特征是,当一个进程正在其关键部分执行,没有其他进程是被允许在其关键部分中执行。也就是说,没有两个进程同时在其关键部分中执行。
  • 临界区问题就是去设计一个协议可以使得线程之间协作。

**进程进出临界区协议 **

在这里插入图片描述

  • 进入临界区前在entry section要请求许可;
  • 离开临界区后在exit section 要归还许可。

** 临界区管理准则 **

  • Mutual exclusion (Mutex):互斥
  • Progress:前进
  • Bounded waiting:有限等待

在这里插入图片描述


有空让进,则一而入,无空等待,有限等待,让权等待。

2 互斥锁

MUTEX LOCKS

  • Operating-systems designers build software tools to solve the critical-section problem. The simplest of these tools is the mutex lock.
    • A process must acquire the lock before entering a critical section;
    • It must release the lock when it exits the critical section.

** 锁的基本操作 **

在这里插入图片描述


原子操作

  • Atomic operations mean the operation can NOT be interrupted while it’s running.
  • 原子操作(原语)是操作系统重要的组成部分,下面2条硬件指令都是原子操作,它们可以被用来实现

对临界区的管理(也就是“锁”)。

  • test_and_set()
  • compare_and_swap()

** 锁的实现 **

在这里插入图片描述


** 忙式等待(BUSY WAITING) **

  • 忙式等待是指占用CPU执行空循环实现等待
  • 这种类型的互斥锁也被称为“自旋锁”(spin lock)
    • 缺点:浪费CPU周期,可以将进程插入等待队列以让出CPU的使用权;
    • 优点:进程在等待时没有上下文切换,对于使用锁时间不长的进程,自旋锁还是可以接受的;在多处理器系统中,自旋锁的优势更加明显。

3 互斥锁实验

  1. 订票系统(临界区的管理)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

int ticketAmount = 2; //Global Variable 

void* ticketAgent(void* arg){
    int t = ticketAmount;
    //sleep(1);
    if (t > 0)
    {
        printf("One ticket sold!\n");
        t--;
    }else{
        printf("Ticket sold out!!\n");
    }
    ticketAmount = t;
    pthread_exit(0);
}

int main(int argc, char const *argv[])
{
    pthread_t ticketAgent_tid[2];

    for (int i = 0; i < 2; ++i)
    {
        pthread_create(ticketAgent_tid+i, NULL, ticketAgent,NULL);
    }

    for (int i = 0; i < 2; ++i)
    {
        pthread_join(ticketAgent_tid[i],NULL);
    }
    
    printf("The left ticket is %d\n", ticketAmount);
    
    return 0;
}

该份代码用一个线程函数创建了两个线程,这种创建方法可以使用循环来减少代码的书写量(23行至28行),30行至33行学习如何用循环来等待所有线程结束。两个线程作为售票终端共享一个全局变量ticketAmount,两个线程运行结束后在主线程中打印余票量,编译运行这份代码,观察结果。
然后找出临界区,用互斥锁对临界区进行管理,阅读并运行下面的代码。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

int ticketAmount = 2; //Global Variable 
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //Global lock

void* ticketAgent(void* arg){
    pthread_mutex_lock(&lock);
    int t = ticketAmount;
    if (t > 0)
    {
        printf("One ticket sold!\n");
        t--;
    }else{
        printf("Ticket sold out!!\n");
    }
    ticketAmount = t;
    pthread_mutex_unlock(&lock);
    pthread_exit(0);
}

int main(int argc, char const *argv[])
{
    pthread_t ticketAgent_tid[2];

    for (int i = 0; i < 2; ++i)
    {
        pthread_create(ticketAgent_tid+i, NULL, ticketAgent,NULL);
    }



    for (int i = 0; i < 2; ++i)
    {
        pthread_join(ticketAgent_tid[i],NULL);
    }
    
    printf("The left ticket is %d\n", ticketAmount);
    
    return 0;
}

代码说明:
a. pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //创建一个互斥锁
b. pthread_mutex_lock(&lock); //上锁
c. pthread_mutex_unlock(&lock); //开锁

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值