gpt4 book ai didi

c++ - 如何在 Windows 上仅使用事件和互锁原语实现递归锁?

转载 作者:行者123 更新时间:2023-11-28 08:01:47 31 4
gpt4 key购买 nike

我写了一个递归锁,其行为类似于临界区。但是我在实现递归功能时遇到了问题。像这样的代码:

#include "own_cs.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>


struct own_critical_section
{
long own_lock_count; // count of locked thread, -1 means unlock , other means lock.
HANDLE own_event; // auto-reset
DWORD own_owning_thread_id; // owner thread of lock
};


void InitialOwnCriticalSection( own_critical_section** own_cs)
{
*own_cs = (own_critical_section*)malloc( sizeof( own_critical_section ) );
(*own_cs)->own_lock_count = -1;
(*own_cs)->own_event = CreateEventW( NULL, FALSE, FALSE, NULL );
(*own_cs)->own_owning_thread_id = 0;
}

void DeleteOwnCriticalSection( own_critical_section* own_cs )
{
assert( own_cs != NULL );

CloseHandle( own_cs->own_event );
free( own_cs );
}

void EnterOwnCriticalSection( own_critical_section* own_cs )
{
for ( int spin_count = 0; spin_count < 500; ++ spin_count )
{//spinlock
if ( -1L == InterlockedCompareExchange( &own_cs->own_lock_count, -1L, -1L ) )
break;
Sleep(0);
}

if( 0 < InterlockedIncrement( &own_cs->own_lock_count ) &&
( own_cs->own_owning_thread_id != ::GetCurrentThreadId() ) ) 
//there is no guarantee that own_owning_thread_id is set before comparison with tid.so this comparison is not thread-safe.
{
//locked
WaitForSingleObject( own_cs->own_event, INFINITE );
}

own_cs->own_owning_thread_id = ::GetCurrentThreadId();
}

void LeaveOwnCriticalSection( own_critical_section* own_cs )
{
if( -1L != InterlockedDecrement( &own_cs->own_lock_count ) &&
(::GetCurrentThreadId() == own_cs->own_owning_thread_id ) )
{
SetEvent( own_cs->own_event );
}
}

问题出在 EnterOwnCriticalSection 例程;正如该函数中的注释,不能保证在与 tid 比较之前设置 own_owning_thread_id。因此这种比较不是线程安全的。

最佳答案

#include "own_cs.h"  
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>


struct own_critical_section
{
long own_lock_count; // count of locked thread, -1 means unlock , other means lock.
HANDLE own_event; // auto-reset
DWORD own_owning_thread_id; // owner thread of lock
long own_recursion_count; // count of recursion
};


void InitialOwnCriticalSection( own_critical_section** own_cs)
{
*own_cs = (own_critical_section*)malloc( sizeof( own_critical_section ) );
(*own_cs)->own_lock_count = -1;
(*own_cs)->own_event = CreateEventW( NULL, FALSE, FALSE, NULL );
(*own_cs)->own_owning_thread_id = 0;
(*own_cs)->own_recursion_count = 0;
}

void DeleteOwnCriticalSection( own_critical_section* own_cs )
{
assert( own_cs != NULL );

CloseHandle( own_cs->own_event );
free( own_cs );
}

void EnterOwnCriticalSection( own_critical_section* own_cs )
{
assert( own_cs->own_lock_count>=-1L );

DWORD current_thread_id = GetCurrentThreadId();

if ( own_cs->own_owning_thread_id != current_thread_id )
{
for ( int spin_count = 0; spin_count < 500; ++ spin_count )
{//spinlock
if ( -1L == InterlockedCompareExchange( &own_cs->own_lock_count, -1L, -1L ) )
break;
Sleep(0);
}
}

// if current thread is the acquired thread,
// own_cs->own_owning_thread_id = current_thread_id
// else if current thread is not the acquired thread
// own_cs->own_owning_thread_id should be 0 or the thread_id which is acquired thread.
if( 0 < InterlockedIncrement( &own_cs->own_lock_count ) &&
( own_cs->own_owning_thread_id != current_thread_id ) )
{
//locked
WaitForSingleObject( own_cs->own_event, INFINITE );
}

// inside lock
++own_cs->own_recursion_count;
own_cs->own_owning_thread_id = current_thread_id;
}

void LeaveOwnCriticalSection( own_critical_section* own_cs )
{
assert( own_cs->own_lock_count>=-1L && own_cs->own_recursion_count>=0 );

if ( --own_cs->own_recursion_count == 0 )
own_cs->own_owning_thread_id = 0;

if( -1L != InterlockedDecrement( &own_cs->own_lock_count ) &&
( 0 == own_cs->own_recursion_count ) )
{
SetEvent( own_cs->own_event );
}
}

上面的代码已更新。我添加评论点。

关于c++ - 如何在 Windows 上仅使用事件和互锁原语实现递归锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11255713/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com