使用Windows slim读/写锁

发布于 2024-12-08 19:14:31 字数 1736 浏览 1 评论 0原文

/*language C code*/

#include "windows.h"

typedef struct object_s
{
    SRWLOCK lock;
    int data;
} object_t, *object_p; /*own and pointer type*/

void thread(object_p x)
{
    AcquireSRWLockExclusive(&x->lock);
    //...do something that could probably change x->data value to 0
    if(x->data==0)
        free(x);
    else
        ReleaseSRWLockExclusive(&x->lock);
}

void main()
{
    int i;
    object_p object=(object_p)malloc(sizeof(object_t));

    InitializeSRWLock(&object->lock);

    for(i=0;i<3;i++)
     CreateThread(0,0,thread,object,0);
}

正如您在上面的代码中可以看出的,我必须完成的是让一个线程有条件地释放其他两个线程可能阻塞的对象。上面的代码显然是有缺陷的,因为如果对象与锁一起被释放,所有阻塞线程只会给我们带来错误。

下面的解决方案

/*language C code*/

#include "windows.h"

typedef struct object_s
{
    /*change: move lock to stack in main()*/
    int data;
} object_t, *object_p; /*own and pointer type*/

void thread(void * x)
{
    struct {
    PSRWLOCK l;
    object_p o;
    } * _x=x;
    AcquireSRWLockExclusive(_x->l);
    //...do something that could probably change x->data value to 0
    if(_x->o->data==0)
        free(_x->o);
    ReleaseSRWLockExclusive(&x->lock);
}

void main()
{
    int i;
    SRWLOCK lock; /*lock over here*/
    object_p object=(object_p)malloc(sizeof(object_t));

    InitializeSRWLock(&lock);

    /*pack for thread context*/
    struct
    {
        PSRWLOCK l;
        object_p o;
    } context={&lock, object};

    for(i=0;i<3;i++)
     CreateThread(0,0,thread,&context,0);
}

在这种情况下有效,但在我的最终项目中不适用,因为实际上存在一个对象的动态链接列表。通过应用这个解决方案,意味着必须有一个相应的锁列表,每个锁对应一个对象,而且,当某个对象被释放时,它的锁必须同时被释放。与第一个代码部分相比,没有什么新内容。

现在我想知道是否有替代解决方案。非常感谢!

/*language C code*/

#include "windows.h"

typedef struct object_s
{
    SRWLOCK lock;
    int data;
} object_t, *object_p; /*own and pointer type*/

void thread(object_p x)
{
    AcquireSRWLockExclusive(&x->lock);
    //...do something that could probably change x->data value to 0
    if(x->data==0)
        free(x);
    else
        ReleaseSRWLockExclusive(&x->lock);
}

void main()
{
    int i;
    object_p object=(object_p)malloc(sizeof(object_t));

    InitializeSRWLock(&object->lock);

    for(i=0;i<3;i++)
     CreateThread(0,0,thread,object,0);
}

As you can figure out in the codes above, what I have to accomplish is to let one thread conditionally free the object on which the other two may block. Codes above are obviously flawed because if object is set free along with the lock, all blocking threads give us nowhere but wrong.

A solution below

/*language C code*/

#include "windows.h"

typedef struct object_s
{
    /*change: move lock to stack in main()*/
    int data;
} object_t, *object_p; /*own and pointer type*/

void thread(void * x)
{
    struct {
    PSRWLOCK l;
    object_p o;
    } * _x=x;
    AcquireSRWLockExclusive(_x->l);
    //...do something that could probably change x->data value to 0
    if(_x->o->data==0)
        free(_x->o);
    ReleaseSRWLockExclusive(&x->lock);
}

void main()
{
    int i;
    SRWLOCK lock; /*lock over here*/
    object_p object=(object_p)malloc(sizeof(object_t));

    InitializeSRWLock(&lock);

    /*pack for thread context*/
    struct
    {
        PSRWLOCK l;
        object_p o;
    } context={&lock, object};

    for(i=0;i<3;i++)
     CreateThread(0,0,thread,&context,0);
}

works in this case but not applicable however, in my final project because there is actually a dynamic linked list of objects. By applying this solution it means that there must be a list of locks accordingly, each lock for an object and moreover, when a certain object is set free, its lock must be set free at the same time. There is nothing new compared with the first code section.

Now I wonder if there is an alternative solution to this. Thank you very much!

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

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

发布评论

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

评论(1

[旋木] 2024-12-15 19:14:31

解决方案是不要将锁与数据一起分配。我建议您将数据移出该结构,并将其替换为指向数据的指针。然后,您的链表可以首先释放数据,然后释放节点,不会出现任何问题。下面是一些伪代码:

typedef struct 
{
  lock_t lock;
  int*   data_ptr;
} something_t;

void init_something (something_t* thing, ...)
{
  thing->lock = init_lock();
  thing->data_ptr = malloc(...);  // whatever the data is supposed to be
}

void free_something (somthing_t* thing)
{
  lock(thing->lock);
    free(thing->data_ptr);
    thing->data_ptr = NULL;
  unlock(thing->lock);
}

...

void linked_list_delete_node (...)
{
  free_something(node_to_delete->thing);
  free(node_to_delete);
}

...

void thread (void* x)
{
  lock(x->lock);
    //...do something that could probably change x->data_ptr->data... to 0
    if(x->data_ptr->data == 0)
    {
      free_something(x->data_ptr->data);
    }
  unlock(x->lock);
}



 AcquireSRWLockExclusive(lock);
  if(_x->o->data==0)
    free(_x);
 ReleaseSRWLockExclusive(lock);

作为旁注,Windows 的 C 程序永远不会返回 void。托管 C 程序必须始终返回 int。您的程序无法在 C 编译器上编译。

此外,CreateThread() 需要一个函数指针,该函数指针指向返回 32 位值并采用 void 指针作为参数的函数。你传递了一种不同类型的函数指针,C 中不允许函数指针强制转换,我也不确定如果 Windows 获得与预期不同的函数指针,它会执行什么样的疯狂操作。您调用未定义的行为。这可能会导致您的程序崩溃或以意外或随机的方式运行。

您需要将线程函数更改为DWORD WINAPI thread (LPVOID param);

The solution is to not allocate the lock together with the data. I would suggest that you move the data out of that struct and replace it with a pointer to the data. Your linked list can then free the data first, and then the node, without any problems. Here's some pseudo code:

typedef struct 
{
  lock_t lock;
  int*   data_ptr;
} something_t;

void init_something (something_t* thing, ...)
{
  thing->lock = init_lock();
  thing->data_ptr = malloc(...);  // whatever the data is supposed to be
}

void free_something (somthing_t* thing)
{
  lock(thing->lock);
    free(thing->data_ptr);
    thing->data_ptr = NULL;
  unlock(thing->lock);
}

...

void linked_list_delete_node (...)
{
  free_something(node_to_delete->thing);
  free(node_to_delete);
}

...

void thread (void* x)
{
  lock(x->lock);
    //...do something that could probably change x->data_ptr->data... to 0
    if(x->data_ptr->data == 0)
    {
      free_something(x->data_ptr->data);
    }
  unlock(x->lock);
}



 AcquireSRWLockExclusive(lock);
  if(_x->o->data==0)
    free(_x);
 ReleaseSRWLockExclusive(lock);

As a sidenote, a C program for Windows can never return void. A hosted C program must always return int. Your program will not compile on a C compiler.

Also, CreateThread() expects a function pointer to a function returning a 32-bit value and taking a void pointer as parameter. You pass a different kind of function pointer, function pointer casts aren't allowed in C, nor am I sure what sort of madness Windows will execute if it gets a different function pointer than what it expects. You invoke undefined behavior. This can cause your program to crash or behave in unexpected or random ways.

You need to change your thread function to DWORD WINAPI thread (LPVOID param);

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