并发队列,C

发布于 2024-11-07 05:29:19 字数 613 浏览 0 评论 0原文

因此,我尝试用 C 实现并发队列。我将方法分为“读取方法”和“写入方法”。因此,当访问 write 方法(如 push() 和 pop())时,我会获取写入器锁。读取方法也是如此。此外,我们可以有多个读者,但只有一名作者。

为了让它在代码中工作,我为整个队列设置了互斥锁。还有两个条件锁 - 一个用于编写者,另一个用于读者。我还有两个整数来跟踪当前使用队列的读取器和写入器的数量。

所以我的主要问题是 - 如何实现多个读者同时访问 read 方法?

目前,这是我的一般读取方法代码:(在伪代码中 - 不是 C。我实际上正在使用 pthreads)。

mutex.lock();
while (nwriter > 0) {
  wait(&reader);
  mutex.unlock();
}
nreader++;
//Critical code
nreader--;
if (nreader == 0) {
  signal(&writer)
}
mutex.unlock

因此,假设我们有一个持有互斥锁的读取器。现在任何其他读者出现并试图获取互斥锁,都将无法做到。不会堵吗?那么有多少读者同时访问read方法呢?

我的推理正确吗?如果是,如何解决问题?

So, I am trying to implement a concurrent queue in C. I have split the methods into "read methods" and "write methods". So, when accessing the write methods, like push() and pop(), I acquire a writer lock. And the same for the read methods. Also, we can have several readers but only one writer.

In order to get this to work in code, I have a mutex lock for the entire queue. And two condition locks - one for the writer and the other for the reader. I also have two integers keeping track of the number of readers and writers currently using the queue.

So my main question is - how to implement several readers accessing the read methods at the same time?

At the moment this is my general read method code: (In psuedo code - not C. I am actually using pthreads).

mutex.lock();
while (nwriter > 0) {
  wait(&reader);
  mutex.unlock();
}
nreader++;
//Critical code
nreader--;
if (nreader == 0) {
  signal(&writer)
}
mutex.unlock

So, imagine we have a reader which holds the mutex. Now any other reader which comes along, and tries to get the mutex, would not be able to. Wouldn't it block? Then how are many readers accessing the read methods at the same time?

Is my reasoning correct? If yes, how to solve the problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

十年九夏 2024-11-14 05:29:19

如果这不是为了练习,请使用 pthread 的读写锁(pthread_rwlock_* 函数)。

另请注意,使用锁保护单个调用可能无法提供必要的正确性保证。例如,从 STL 队列中弹出元素的典型代码是:

if( !queue.empty() ) {
    data = queue.top();
    queue.pop();
}

即使在队列方法内部使用锁,这在并发代码中也会失败,因为从概念上讲,此代码必须是原子事务,但实现不提供此类保证。线程可能会弹出与 top() 读取的元素不同的元素,或者尝试从空队列中弹出,等等。

If this is not for an exercise, use read-write lock from pthreads (pthread_rwlock_* functions).

Also note that protecting individual calls with a lock stil might not provide necessary correctness guarantees. For example, a typical code for popping an element from STL queue is

if( !queue.empty() ) {
    data = queue.top();
    queue.pop();
}

And this will fail in concurrent code even if locks are used inside the queue methods, because conceptually this code must be an atomic transaction, but the implementation does not provide such guarantees. A thread may pop a different element than it read by top(), or attempt to pop from empty queue, etc.

挖鼻大婶 2024-11-14 05:29:19

请找到以下读\写函数。

在我的函数中,我使用 canRead 和 canWrite 互斥体以及 nReads 来表示读取器的数量:

写入函数:

lock(canWrite) // Wait if mutex if not free
// Write
unlock(canWrite)

读取函数:

lock(canRead) // This mutex protect the nReaders
nReaders++    // Init value should be 0 (no readers)
if (nReaders == 1) // No other readers
{
   lock(canWrite)  // No writers can enter critical section
}
unlock(canRead)

// Read

lock(canRead)
nReaders--;
if (nReaders == 0) // No more readers
{
   unlock(canWrite) // Writer can enter critical secion
}
unlock(canRead)

Please find the following read\write functions.

In my functions, I used canRead and canWrite mutexes and nReads for number of readers:

Write function:

lock(canWrite) // Wait if mutex if not free
// Write
unlock(canWrite)

Read function:

lock(canRead) // This mutex protect the nReaders
nReaders++    // Init value should be 0 (no readers)
if (nReaders == 1) // No other readers
{
   lock(canWrite)  // No writers can enter critical section
}
unlock(canRead)

// Read

lock(canRead)
nReaders--;
if (nReaders == 0) // No more readers
{
   unlock(canWrite) // Writer can enter critical secion
}
unlock(canRead)
染柒℉ 2024-11-14 05:29:19

一个经典的解决方案是多个读者、一个作者。

数据结构一开始就没有读者和作者。

您允许任意数量的并发读者。

当一个作家出现时,你会阻止他,直到所有当前读者完成;然后你让他走(任何新的读者和作家,如果作家被阻止,就按顺序在他后面排队)。

A classic solution is multiple-readers, single-writer.

A data structure begins with no readers and no writers.

You permit any number of concurrent readers.

When a writer comes along, you block him till all current readers complete; then you let him go (any new readers and writers which come along which the writer is blocked queue up behind him, in order).

岁月苍老的讽刺 2024-11-14 05:29:19

你可以尝试这个库,它是用c原生构建的,无锁,适合跨平台lfqueue

例如:-

int* int_data;
lfqueue_t my_queue;

if (lfqueue_init(&my_queue) == -1)
    return -1;

/** Wrap This scope in other threads **/
int_data = (int*) malloc(sizeof(int));
assert(int_data != NULL);
*int_data = i++;
/*Enqueue*/
 while (lfqueue_enq(&my_queue, int_data) == -1) {
    printf("ENQ Full ?\n");
}

/** Wrap This scope in other threads **/
/*Dequeue*/
while  ( (int_data = lfqueue_deq(&my_queue)) == NULL) {
    printf("DEQ EMPTY ..\n");
}

// printf("%d\n", *(int*) int_data );
free(int_data);
/** End **/

lfqueue_destroy(&my_queue);

You may try this library it is built in c native, lock free, suitable for cross-platform lfqueue,

For Example:-

int* int_data;
lfqueue_t my_queue;

if (lfqueue_init(&my_queue) == -1)
    return -1;

/** Wrap This scope in other threads **/
int_data = (int*) malloc(sizeof(int));
assert(int_data != NULL);
*int_data = i++;
/*Enqueue*/
 while (lfqueue_enq(&my_queue, int_data) == -1) {
    printf("ENQ Full ?\n");
}

/** Wrap This scope in other threads **/
/*Dequeue*/
while  ( (int_data = lfqueue_deq(&my_queue)) == NULL) {
    printf("DEQ EMPTY ..\n");
}

// printf("%d\n", *(int*) int_data );
free(int_data);
/** End **/

lfqueue_destroy(&my_queue);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文