c - 无锁缓冲区

标签 c thread-safety locking buffer c99

在我的代码中,我有一个缓冲区,向其中添加数据的代码是:

bool push_string(file_buffer *cb, const char* message, const unsigned short msglen)
{
    unsigned int size = msglen;

    if(cb->head >= (cb->size - size))
    {
        size = cb->size - cb->head - 1;
    }

    if(size < 1) return false;

    char* dest = cb->head += size;

    memcpy(dest, message, size);

    return (size == msglen);
}

由于我从多个中断添加数据(可以互相免除),我想知道这段代码是否是线程安全的?我将“cb->head”标记为 volatile ,但如果另一个中断恰好在“head”的增加和对“dest”的分配之间被免除,则事情可能会出错。

如何改进此代码以使其更安全?

编辑:也许我不应该使用术语“线程安全”,因为没有并行运行的线程,只有中断的可能性。

最佳答案

C99 没有线程的概念,因此也没有线程保护的概念。只有C11有。 在 C99 中,唯一中断安全的数据类型是 sig_atomic_t,但显然这也没有说明线程。

通常,您尝试同时访问数据结构是完全错误的, volatile 根本不能保证您收到合理的数据。即使在 C11 中,也无法保证任何操作的原子性,因此您可能会遇到指针值的下半部分已写入但上半部分尚未写入的情况。这可能会给你一个完全虚假的结果。由于这种事情可能百万分之一或在特殊情况下(例如重负载)发生一次,这可能会导致很难追踪的错误。

不要这样做。

C11 为您提供了处理此类事务的新工具,特别是原子操作。它尚未完全实现,但许多编译器已经具有可以帮助您的扩展。我已将其中一些包装在 P99 中宏包,因此通过某些编译器,您从今天起就可以开始使用这些功能。

关于c - 无锁缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14436333/

相关文章:

C#:为迭代正确锁定队列

c - 输出和输入二进制数据 C

计算和使用 uint32_t 的最大值

c - 结构中一个字段的值无意中变成了另一个字段的值

c# - 在 .Net 中,许多静态类是线程安全的,这是如何实现的?

database - 什么时候锁定数据库表?

c++ - 让我的程序保持活力的神奇cout

java - 表示声纳/雷达/回声位置的数据类型

java - 以一种有效的方式使用 ByteBuffer 将 header 和数据布局打包在一个字节数组中?

delphi - DWScript 是线程安全的吗?