Lamport Bakery算法

一、原理

面包店算法(Bakery Algorithm)是一个用于实现多进程或多线程之间同步的算法,由荷兰计算机科学家Edsger W. Dijkstra于1974年提出。这个算法的名称来源于现实生活中面包店的取号系统。

面包店算法的具体实现如下:

  • 每个线程(或进程)想要进入临界区执行时,必须先拿一个号码。拿号码的规则是查看所有线程的号码,拿一个比所有人号码都大的号码,或者在没有线程在临界区的情况下,可以拿号码0。这个过程类似于面包店里的取号系统,客人进门取一个比当前所有等待的客人号码都大的号。
  • 线程进入临界区的规则是,号码小的线程优先进入。如果两个线程号码相同,则线程ID小的优先进入。这就像面包店服务员为号码小的客人服务。
  • 线程完成临界区的任务后,会将自己的号码设置为0,表示已经退出临界区。

面包店算法中的关键在于解决线程在拿号码时的冲突,以及持有相同号码时的优先级问题,这样可以保证每个线程都有机会进入临界区,从而避免了饥饿现象,实现了公平的资源访问。

二、C++代码实现

#include <iostream>
#include <thread>
#include <atomic>
#include <vector>
#include <array>
#include <algorithm>

constexpr int loop_count = 5;
constexpr int thread_count = 10;

// 0或1,代表正在取票与否
std::array<int, thread_count> choosing;
// 票号
std::array<int, thread_count> tickets;

void critical_region(int thread_id) {
    std::cout << "thread " << thread_id << " is in critical_region" << '\n';
}

void non_critical_region(int thread_id) {
    std::cout << "thread " << thread_id << " is in non_critical_region" << '\n';
}

void lamport_bakery_algorithm(int thread_id) {
    for (int loop = 0; loop < loop_count; loop++) {
        // 取票
        choosing[thread_id] = 1;
        tickets[thread_id] = 1 + *std::max_element(&tickets[0], &tickets[thread_count - 1]);
        choosing[thread_id] = 0;

        // 拿面包
        for (int i = 0; i < thread_count; i++) {
            // 有线程正在取票,让出cpu
            while (choosing[i] == 1) {
                std::this_thread::yield();
            }
            // 有线程的票号较小,或票号相等但线程号较小,让出cpu
            while (tickets[i] != 0 && (tickets[i] < tickets[thread_id] || (tickets[i] == tickets[thread_id] && i < thread_id))) {
                std::this_thread::yield();
            }
        }

        // 执行临界区代码
        critical_region(thread_id);
        // 票号重置
        tickets[thread_id] = 0;
        // non_critical_region(thread_id);
    }
}

int main() {
    std::vector<std::thread> thread_pool;
    for (int i = 0; i < thread_count; i++) {
        choosing[i] = 0;
        tickets[i] = 0;
        thread_pool.push_back(std::thread(lamport_bakery_algorithm, i));
    }

    for (auto& thread : thread_pool) {
        thread.join();
    }
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Lamport时钟算法是一种用于分布式系统中的逻辑时钟算法,由著名计算机科学家Leslie Lamport提出。它通过引入逻辑时钟的概念,实现了对分布式系统中事件的有序性和并发性的控制。 Lamport时钟由一个全局逻辑时钟和一组局部逻辑时钟组成。每个进程都有一个局部时钟,用于记录该进程自身发生的事件。当一个进程发生了一个事件,它自增自己的局部时钟,并给该事件赋予一个时间戳。时间戳由进程的标识和局部时钟值组成。 Lamport时钟算法的关键概念是「happen-before」关系,即如果事件A在事件B之前发生,那么A必须在B的时间戳上小于B的时间戳。通过捕捉事件之间的先后关系,Lamport时钟算法实现了对事件的有序性的控制。 在Lamport时钟算法中,当一个进程需要发送消息给另一个进程时,它将自己的时间戳附加在消息上。接收到消息的进程会更新自己的局部时钟和全局时钟,保持时间戳的递增有序性。 尽管Lamport时钟算法可以实现对事件的有序性的控制,但是它并不能准确地保证两个事件的时间间隔,因为不同进程的本地时钟可能存在不同步的情况。所以Lamport时钟算法只能保证事件发生的先后顺序,而不能精确测量时间间隔。 总结来说,Lamport时钟算法是一种分布式系统中的逻辑时钟算法,通过引入逻辑时钟和时间戳的概念,实现了对事件的先后顺序的控制。该算法可以帮助我们在分布式环境中处理并发性和有序性的问题,但不能准确地测量时间间隔。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值