2017-04-12 74 views
0

我有一个我个人实现的数据结构,现在需要跨多个线程使用。C - 如何使我的数据结构实现同步?

typedef struct 
{ 
    void** array_of_elements; 
    size_t size; 
} myStruct; 

为简单起见,假设我的数据结构具有以下功能:

// Gets a data element from the structure. 
void* get(myStruct *x); 
// Prints out all the data elements. 
void print(myStruct *x); 
// Adds an element into the structure. 
void add(myStruct *x, void *to_be_added); 

这是不以任何形式叫get,而另一个线程正在调用print因为他们是两个访问的问题。但是,getprint无法正常工作,而add正在调用中。反之亦然,add不能工作,如果getprint目前正在进行中。

因此,我改变myStruct看起来像下面这样:

typedef struct 
{ 
    void** array_of_elements; 
    size_t size; 

    // True when a mutator is editing this struct. 
    bool mutating; 
    // The number of threads currently accessing this struct. 
    int accessors; 
} myStruct; 

现在我的功能如下所示:

void* get(myStruct *x) 
{ 
    // Wait for mutating to end. 
    while (x->mutating); 
    // Indicate that another accessor is now using this struct. 
    x->accessors++; 

    // get algorithm goes here 

    // Declare we are finished reading. 
    x->accessors--; 

    return ... 
} 

// Same as above... 
void print(myStruct *x) 
... 

void add(myStruct *x) 
{ 
    // Wait for any accessors or mutators to finish. 
    while (x->mutating || x->accessors > 0);  
    x->mutating = true; 

    // add algorithm here 

    x->mutating = false; 
} 

,我觉得有很多的问题,这的方法,我找不到解决方法:

  • 我的一位同学告诉我,使用while循环会减慢线程的速度。
  • 它没有排队感。开始等待myStruct完成使用的第一种方法不一定是接下来的方法。
  • 即使如果我有一个队列数据结构的线程去下,数据结构也需要同步,这本身是一个无限循环需要一个同步数据结构来同步自己
  • 我认为可能在相同的纳秒中,一个线程将accessors计数器从0更改为1(这意味着它们要开始读取),但是可能突变线程看到它的值为0并开始变异。然后,mutator线程和访问器线程将同时进行。
  • 我敢肯定,这个逻辑可能会导致网格锁定(线程无限等待)。
  • 我不知道如何使某些线程在需要执行此任务时能够睡眠并唤醒,除了它被卡在while循环中。
+0

研究读写锁... – Dmitri

+0

@Dmitri我读写锁的程度如何,甚至不会远远接近实际实现的样子? – Hatefiend

+0

如果你在线程之间共享一个变量,你应该使用原子访问或者像互斥体那样的某种同步机制。读写锁就像一个互斥锁,只是它允许多个线程读取,但需要独占访问才能写入。对于posix线程,有'pthread_rwlock_t',并且windows有“slim reader writer locks” – Dmitri

回答

0

你有正确的想法,只是错误的方法。我不确定你正在编写什么操作系统,但是你想看看mutexsemaphore的概念来做你想做的事情。

在Linux/Unix是POSIX兼容的,你可以看看并行线程:

http://www.cs.wm.edu/wmpthreads.html

在Windows上,你可以看看Critical Sections的东西接近mutex概念:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx

WaitForMultipleObjects用于接近某个东西semaphore

https://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx

而且,是的,使用while循环是一个坏主意。在这种情况下,您正在使用所谓的繁忙循环。在这里就可以了更多阅读:

What is a busy loop?

使用mutexsemaphore,没有while循环是必需的。祝你好运!

+0

那么实现是依赖于库的?这看起来不正确。我想我的'结构'里面,我需要添加一些变量来锁定我的线程,因为我的'struct' **是互斥体**? – Hatefiend

+0

让我重申一下:有没有办法在不使用任何线程库的情况下执行此操作?使用我的结构的开发人员可能不在我设计的操作系统上。相反,我可以在我的'struct'中只是有一个变量来指示何时使用'struct'或不安全吗? – Hatefiend

+0

@Hatefiend如果你不想把你的代码绑定到任何特定的线程API,最好把锁定保留给用户,而不是试图实现你自己的一次性互斥或读写锁定(可能会比你期望的更难以正确执行)。他们所需要做的就是在调用访问函数之前/之后获取/释放他们选择的锁(可能是与他们使用的任何线程实现一起使用的锁)。 – Dmitri