C语言实现读写锁和try...catch逻辑

本文详细介绍了C语言中使用读写锁(RWLock)实现线程安全共享资源访问的代码示例,以及如何使用setjmp和longjmp模拟try...catch语句处理错误。
摘要由CSDN通过智能技术生成

1. 读写锁代码实现

代码示例创建了多个读者线程和一个写者线程来访问共享资源(这里是一个文件)。在读者线程中,使用了文件I/O函数打开文件、映射文件到内存,并对文件内容进行了读取。在写者线程中,也使用了文件I/O函数打开文件、映射文件到内存,并对文件内容进行了写入。完整代码如下,简洁易懂。

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

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

// 定义读写锁结构体
typedef struct
{
    pthread_mutex_t mutex;     // 互斥锁,保护对读写锁的访问
    pthread_cond_t read_cond;  // 读条件变量,用于同步读操作
    pthread_cond_t write_cond; // 写条件变量,用于同步写操作
    int readers;               // 当前读者的数量
    int writer;                // 当前写者的数量(0或1)
} rwlock_t;

// 初始化读写锁
void rwlock_init(rwlock_t *lock)
{
    lock->readers = 0;
    lock->writer = 0;
    pthread_mutex_init(&lock->mutex, NULL);
    pthread_cond_init(&lock->read_cond, NULL);
    pthread_cond_init(&lock->write_cond, NULL);
}

// 上读锁
void rwlock_read_lock(rwlock_t *lock)
{
    pthread_mutex_lock(&lock->mutex);
    while (lock->writer > 0)
    { // 若有写者存在,等待
        pthread_cond_wait(&lock->read_cond, &lock->mutex);
    }
    lock->readers++; // 读者数量增加
    pthread_mutex_unlock(&lock->mutex);
}

// 解读锁
void rwlock_read_unlock(rwlock_t *lock)
{
    pthread_mutex_lock(&lock->mutex);
    lock->readers--; // 读者数量减少
    if (lock->readers == 0)
    { // 最后一个读者解锁时唤醒写者
        pthread_cond_signal(&lock->write_cond);
    }
    pthread_mutex_unlock(&lock->mutex);
}

// 上写锁
void rwlock_write_lock(rwlock_t *lock)
{
    pthread_mutex_lock(&lock->mutex);
    while (lock->readers > 0 || lock->writer > 0)
    { // 若有读者或写者存在,等待
        pthread_cond_wait(&lock->write_cond, &lock->mutex);
    }
    lock->writer = 1; // 写者存在
    pthread_mutex_unlock(&lock->mutex);
}

// 解写锁
void rwlock_write_unlock(rwlock_t *lock)
{
    pthread_mutex_lock(&lock->mutex);
    lock->writer = 0; // 写者不存在
    if (lock->readers > 0)
    { // 唤醒所有读者
        pthread_cond_broadcast(&lock->read_cond);
    }
    else
    { // 或者唤醒一个写者
        pthread_cond_signal(&lock->write_cond);
    }
    pthread_mutex_unlock(&lock->mutex);
}

// 示例使用读写锁的线程函数
void *reader_thread(void *arg)
{
    rwlock_t *lock = (rwlock_t *)arg;
    printf("Reader thread start.\n");

    rwlock_read_lock(lock);
    printf("Reading data...\n");
    // 进行读操作

    int fd = open("./shmem.c", O_RDONLY);

    if (fd == -1)
    {
        perror("Error opening file");
        return EXIT_FAILURE;
    }

    unsigned char *addr = (unsigned char *)mmap(NULL, 753, PROT_READ, MAP_SHARED, fd, 0);

    if (addr == MAP_FAILED)
    {
        perror("Error mapping file");
        close(fd);
        return EXIT_FAILURE;
    }

    // Print the content byte by byte
    for (int i = 0; i < 753; ++i)
    {
        printf("%c", addr[i]);
    }
    printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");

    if (munmap(addr, 753) == -1)
    {
        perror("Error unmapping file");
        close(fd);
        return EXIT_FAILURE;
    }

    close(fd);

    rwlock_read_unlock(lock);
    printf("Reader thread end.\n");
    return NULL;
}

void *writer_thread(void *arg)
{
    rwlock_t *lock = (rwlock_t *)arg;
    printf("Writer thread start.\n");

    rwlock_write_lock(lock);
    printf("Writing data...\n");
    // 进行写操作
    int fd = open("./shmem.c", O_RDWR);

    if (fd == -1)
    {
        perror("Error opening file");
        return NULL;
    }

    unsigned char *addr = (unsigned char *)mmap(NULL, 753, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    if (addr == MAP_FAILED)
    {
        perror("Error mapping file");
        close(fd);
        return NULL;
    }

    // Print the content byte by byte
    for (int i = 0; i < 753; i++)
    {
        addr[i] = 'm';
    }

    if (munmap(addr, 753) == -1)
    {
        perror("Error unmapping file");
        close(fd);
        return NULL;
    }

    close(fd);

    rwlock_write_unlock(lock);
    printf("Writer thread end.\n");
    return NULL;
}

int main()
{
    pthread_t readers[3];
    pthread_t writer;

    rwlock_t lock;
    rwlock_init(&lock);

    for (int i = 0; i < 3; i++)
    {
        pthread_create(&readers[i], NULL, reader_thread, &lock);
    }
    pthread_create(&writer, NULL, writer_thread, &lock);

    for (int i = 0; i < 3; i++)
    {
        pthread_join(readers[i], NULL);
    }
    pthread_join(writer, NULL);

    return 0;
}

2. try…catch

在C语言中,没有像其他编程语言中的原生支持的try-catch语句。但你可以使用setjmplongjmp函数来实现类似的错误处理机制。

未完待续。。。。。。。。。。。。下面是仅是一种简单的实现示例

下面是一个简单的示例代码,演示了如何使用setjmplongjmp来实现try-catch风格的错误处理:

#include <stdio.h>
#include <setjmp.h>

jmp_buf jmp_buffer;

void divide(int a, int b)
{
    if (b == 0)
    {
        printf("Error: Division by zero\n");
        longjmp(jmp_buffer, 1);
    }
    else
    {
        int result = a / b;
        printf("Result: %d\n", result);
    }
}

int main()
{
    if (setjmp(jmp_buffer) == 0)
    {
        // 这里是try块
        divide(10, 0);
        divide(20, 5);
    }
    else
    {
        // 这里是catch块
        printf("Exception caught\n");
    }

    return 0;
}

在上面的示例代码中,setjmp用于设置一个跳转点,并返回0。然后,divide函数被调用,如果除数为0,则会调用longjmp跳转回setjmp所设置的跳转点,并返回非零值。在setjmp之后的代码就相当于try块,如果发生错误,则会在longjmp处跳转到setjmp之后,并执行else块作为catch块来处理异常。

需要注意的是,setjmplongjmp的使用需要非常小心,因为它们会绕过正常的函数调用和返回机制,可能导致资源泄漏或非预期的行为。此外,setjmplongjmp只能用于跳出当前的函数范围,不能跨越多个函数。在实际使用中,请务必谨慎并遵循最佳的错误处理实践。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值