线程同步之EVENT

事件可传信给其他线程,表示某些条件现在已具备,比如有可用的消息。

事件可分为手动复位和自动复位,前者可传信给许多同时等待事件的线程而且可以被复位。

自动复位的事件传信给单个等待时间的线程,该事件会自动复位。

Applications can use event objects in a number of situations to notify a waiting thread of the occurrence of an event. For example, overlapped I/O operations on files, named pipes, and communications devices use an event object to signal their completion. 

The following example(From MSDN)uses event objects to prevent several threads from reading from a shared memory buffer while a master thread is writing to that buffer. First, the master thread uses the CreateEvent function to create a manual-reset event object whose initial state is nonsignaled. Then it creates several reader threads. The master thread performs a write operation and then sets the event object to the signaled state when it has finished writing.

Before starting a read operation, each reader thread uses WaitForSingleObject to wait for the manual-reset event object to be signaled. When WaitForSingleObject returns, this indicates that the main thread is ready for it to begin its read operation.

#include 
   
   
    
    
#include 
    
    
     
     

#define THREADCOUNT 4

HANDLE ghWriteEvent;
HANDLE ghThreads[THREADCOUNT];

DWORD WINAPI ThreadProc(LPVOID);

void CreateEventsAndThreads(void)
{
    int i;
    DWORD dwThreadID;

    // Create a manual-reset event object. The write thread sets this
    // object to the signaled state when it finishes writing to a
    // shared buffer.

    ghWriteEvent = CreateEvent(
        NULL,               // default security attributes
        TRUE,               // manual-reset event
        FALSE,              // initial state is nonsignaled
        TEXT("WriteEvent")  // object name
        );

    if (ghWriteEvent == NULL)
    {
        printf("CreateEvent failed (%d)\n", GetLastError());
        return;
    }

    // Create multiple threads to read from the buffer.

    for(i = 0; i < THREADCOUNT; i++)
    {
        // TODO: More complex scenarios may require use of a parameter
        //   to the thread procedure, such as an event per thread to
        //   be used for synchronization.
        ghThreads[i] = CreateThread(
            NULL,              // default security
            0,                 // default stack size
            ThreadProc,        // name of the thread function
            NULL,              // no thread parameters
            0,                 // default startup flags
            &dwThreadID);

        if (ghThreads[i] == NULL)
        {
            printf("CreateThread failed (%d)\n", GetLastError());
            return;
        }
    }
}

void WriteToBuffer(VOID)
{
    // TODO: Write to the shared buffer.

    printf("Main thread writing to the shared buffer...\n");

    // Set ghWriteEvent to signaled

    if (! SetEvent(ghWriteEvent) )
    {
        printf("SetEvent failed (%d)\n", GetLastError());
        return;
    }
}

void CloseEvents()
{
    // Close all event handles (currently, only one global handle).

    CloseHandle(ghWriteEvent);
}

int main( void )
{
    DWORD dwWaitResult;

    // TODO: Create the shared buffer

    // Create events and THREADCOUNT threads to read from the buffer

    CreateEventsAndThreads();

    // At this point, the reader threads have started and are most
    // likely waiting for the global event to be signaled. However,
    // it is safe to write to the buffer because the event is a
    // manual-reset event.

    WriteToBuffer();

    printf("Main thread waiting for threads to exit...\n");

    // The handle for each thread is signaled when the thread is
    // terminated.
    dwWaitResult = WaitForMultipleObjects(
        THREADCOUNT,   // number of handles in array
        ghThreads,     // array of thread handles
        TRUE,          // wait until all are signaled
        INFINITE);

    switch (dwWaitResult)
    {
        // All thread objects were signaled
        case WAIT_OBJECT_0:
            printf("All threads ended, cleaning up for application exit...\n");
            break;

        // An error occurred
        default:
            printf("WaitForMultipleObjects failed (%d)\n", GetLastError());
            return 1;
    }

    // Close the events to clean up

    CloseEvents();

    return 0;
}

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
    // lpParam not used in this example.
    UNREFERENCED_PARAMETER(lpParam);

    DWORD dwWaitResult;

    printf("Thread %d waiting for write event...\n", GetCurrentThreadId());

    dwWaitResult = WaitForSingleObject(
        ghWriteEvent, // event handle
        INFINITE);    // indefinite wait

    switch (dwWaitResult)
    {
        // Event object was signaled
        case WAIT_OBJECT_0:
            //
            // TODO: Read from the shared buffer
            //
            printf("Thread %d reading from buffer\n",
                   GetCurrentThreadId());
            break;

        // An error occurred
        default:
            printf("Wait error (%d)\n", GetLastError());
            return 0;
    }

    // Now that we are done reading the buffer, we could use another
    // event to signal that this thread is no longer reading. This
    // example simply uses the thread handle for synchronization (the
    // handle is signaled when the thread terminates.)

    printf("Thread %d exiting\n", GetCurrentThreadId());
    return 1;
}
/*Thread 4516 waiting for write event...
Thread 5156 waiting for write event...
Main thread writing to the shared buffer...
Main thread waiting for threads to exit...
Thread 5156 reading from buffer
Thread 5156 exiting
Thread 8824 waiting for write event...
Thread 8824 reading from buffer
Thread 4516 reading from buffer
Thread 8824 exiting
Thread 4516 exiting
Thread 11724 waiting for write event...
Thread 11724 reading from buffer
Thread 11724 exiting
All threads ended, cleaning up for application exit...

Process returned 0 (0x0)   execution time : 0.557 s
Press any key to continue.
*/

    
    
   
   


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C# 中,线程并发和线程同步是处理多线程编程中重要的概念。 线程并发指的是多个线程同时执行,这可能导致资源竞争和不确定的结果。为了避免这种情况,我们可以使用线程同步机制来确保线程之间的协调和有序执行。 C# 提供了多种线程同步的机制,下面是一些常用的方法: 1. 互斥锁(Mutex):互斥锁是一种排他锁,只允许一个线程访问被保护的资源。可以使用 `Mutex` 类来创建和管理互斥锁。 2. 信号量(Semaphore):信号量是一种计数器,用于控制同时访问某个资源的线程数。可以使用 `Semaphore` 类来创建和管理信号量。 3. 自旋锁(SpinLock):自旋锁是一种忙等待锁,线程会一直尝试获取锁,直到成功为止。可以使用 `SpinLock` 结构来创建和管理自旋锁。 4. 互斥量(Mutex):互斥量是一种特殊的信号量,只能被一个线程持有。可以使用 `Mutex` 类来创建和管理互斥量。 5. 事件(Event):事件是一种同步机制,在多个线程之间发送信号进行通信。可以使用 `ManualResetEvent` 或 `AutoResetEvent` 类来创建和管理事件。 除了上述方法外,还有一些其他的线程同步机制,如读写锁(ReaderWriterLock)、条件变量(Monitor)等。选择适合场景的线程同步机制很重要,以确保线程安全和性能。 需要注意的是,线程并发和线程同步是一个复杂的主题,需要深入学习和实践才能掌握。在编写多线程代码时,建议仔细考虑并发问题,并使用适当的线程同步机制来确保代码的正确性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值