使用 Windows slim 读/写锁
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7687118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Windows slim read/write lock
提问by Y.Z
/*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!
现在我想知道是否有替代解决方案。非常感谢!
采纳答案by Lundin
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.
作为旁注,Windows 的 C 程序永远不会返回 void。托管的 C 程序必须始终返回 int。您的程序不会在 C 编译器上编译。
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.
此外,CreateThread() 需要一个函数指针,该函数指针返回一个 32 位值并接受一个 void 指针作为参数。您传递了不同类型的函数指针,C 中不允许函数指针强制转换,我也不确定如果 Windows 获得与预期不同的函数指针,它将执行什么样的疯狂。您调用未定义的行为。这可能会导致您的程序崩溃或以意外或随机的方式运行。
You need to change your thread function to DWORD WINAPI thread (LPVOID param);
您需要将线程函数更改为 DWORD WINAPI thread (LPVOID param);