What is the best way to wait for a variable in a m

2019-04-21 18:48发布

I would like to do something like the below for a multi-threaded program:

// wait for variable to become true but don't hog resources  
// then re-sync queues  

Is something like this a good solution?

while (!ready) {
    Thread.Sleep(250); // pause for 1/4 second;
};

8条回答
女痞
2楼-- · 2019-04-21 19:28

The code above will work, and maybe appropriate in some circumstances.

You could also look at a critical section or semaphore - this will make your application block and wait until the resource becomes available,

Your thread that does the work grabs the mutex, does some work, meanwhile, the main method also tries to grab the same mutex, but can't. when the worker thread(s) exit, they release the mutex and your main thread can pass the critical section and continue.

查看更多
闹够了就滚
3楼-- · 2019-04-21 19:32

First of all, you need to declare your 'ready' variable at least 'volatile' or this could have nasty side effects. Secondly, sleeping that long vefore reevaluating the condition is only a good idea if the duration it might take is indeed very long, let's say a few minutes.

Using the WinAPI's Event functions (CreateEvent, SetEvent(), WaitForSingleEvent()) is the best way to do it. Of course it introduces some overhead, but usually it's fine.

If you want to stick with your solution, looping and rechecking the condition a few times before you sleep again could improve performance in some scenarios.

查看更多
Anthone
4楼-- · 2019-04-21 19:33

Try to use Event (kernel object) instead of simple variable and replace your loop by:

WaitForSingleObject(hEventHandle, INFINITE);
查看更多
forever°为你锁心
5楼-- · 2019-04-21 19:38

Here's how you do it using boost:

boost::condition_variable condvar;
boost::mutex mutex;
bool finished1 = false;
bool finished2 = false;

void longComputation1()
{
    {
        boost::lock_guard<boost::mutex> lock(mutex);
        finished1 = false;
    }
    // Perform long computation
    {
        boost::lock_guard<boost::mutex> lock(mutex);
        finished1 = true;
    }
    condvar.notify_one();
}

void longComputation2()
{
    {
        boost::lock_guard<boost::mutex> lock(mutex);
        finished2 = false;
    }
    // Perform long computation
    {
        boost::lock_guard<boost::mutex> lock(mutex);
        finished2 = true;
    }
    condvar.notify_one();
}

void somefunction()
{
    // Wait for long computations to finish without "spinning"
    boost::lock_guard<boost::mutex> lock(mutex);
    while(!finished1 && !finished2)
    {
        condvar.wait(lock);
    }

    // Computations are finished
}

For the sake of brevity, I didn't include the thread spawning code.

The boost::lock_guard uses the RAII idiom to automatically unlock the mutex when the lock object goes out of scope. Very useful for preventing deadlocks in case of exceptions.

I find condition variables less error prone than Microsoft's Event objects. If you use boost.Thread, you'll have the added benefit of cross-platform potability.

查看更多
Ridiculous、
6楼-- · 2019-04-21 19:41

No, this is not a good solution. First it might sleep too long. Second it's easy for threads to get into lockstep. Here's couple of links to MSDN articles on proper synchronization techniques:

查看更多
男人必须洒脱
7楼-- · 2019-04-21 19:45

The raw Win32 API has EVENT for doing this, here's a usage example:

http://msdn.microsoft.com/en-us/library/ms686915(VS.85).aspx

However, that API is C-oriented and particular to Windows. If writing a C++ program you might consider making your code more platform independent by using something like boost::threads, which has an analogue in Conditions.

A caveat I've found is that Windows can WaitForMultipleObjects, thus waiting on several events (and other handle classes) at a time. boost has no parallel AFAIK.

查看更多
登录 后发表回答