I need to know how i did? Any review will be appreciated...

/**program description:
*
* this simple program represents
* the basic concept of threads.
* main() process will create a
* thread that calculate numbers
* while main() output the results.
* main() and threadProcess() share
* share data from a same memory.
* threadProcess() add two numbers
* and dump the result into totalNumber.
* On the other hand, main() uses
* totalNumber to output the result.
* Thus, totalNumber is the shared scope.
* To avoid collision, i used mutex.
*
*/

#include <iostream>
#include <windows.h>
using namespace std;

int totalNumber = 0;
bool threadStarted = false;

HANDLE mutexHandle = NULL;

void threadProcess()
{
    threadStarted = true;

    for (int i=0; i < 10; i++)
    {
        WaitForSingleObject(mutexHandle, INFINITE);

        cout<<"threadProcess() is calculating: "<<endl;
        totalNumber += i;

        //make thread procedure in same
        //speed as main() process
        Sleep(10);

        ReleaseMutex(mutexHandle);
    }
}

int main()
{
    mutexHandle = CreateMutex(NULL, false, NULL);

    HANDLE threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadProcess, NULL, 0, NULL);

    //let thread starts first - main()
    //somewhat starts faster than the
    //spwaned process
    while(!threadStarted) { }

    for(int i = 0; i < 10; i++)
    {
        WaitForSingleObject(mutexHandle, INFINITE);

        cout<<"main() is giving out solution: "<<endl;
        cout<<totalNumber<<endl;

        //make main() process run in same speed
        //with the created thread
        Sleep(10);

        ReleaseMutex(mutexHandle);
    }
    
    //wait for the thread to finish
    //in case its hanging around
    WaitForSingleObject(threadHandle, INFINITE);
    CloseHandle(mutexHandle);

    cin.get();
    return 0;
}

Recommended Answers

All 9 Replies

You should be pleased with your first attempt, it demonstrates threading nicely.
There are some criticisms I would make:
Your mutex isn't actually achieving much - totalNumber is only being updated by one thread. main() is just reading it, so no protection is necessary in this case. If you are using the mutex for synchronisation, well that isn't happening because each thread is releasing the mutex, then immediately trying to grab it again. You don't know which thread will get control.
What's the Sleep(10) for? If you are trying to ensure that control passes to the other thread it would be better placed after the ReleaseMutex() call. In any case, using Sleep() to try and synchronise threads is not a practical solution.
Just an idea, but why not try to implement this project using Events instead of a mutex. You could have an event for each thread to indicate when it has completed it's loop. Each thread checks the other thread's Event and proceeds when signalled. That would give you fully syncronised and more robust code (and a bit more practice:) ).

main() is just reading it, so no protection is necessary in this case.

That's wrong, almost 100% sure, couldn't make sure with google, but it's just 2 threads trying to access the same memory: doesn't matter if they read or write, both will lead to errors.

Agreed on not using Sleep(). It's a useless function: wait for events to happen, don't guess how long such and such is going to take, and put that time in Sleep().

That's wrong, almost 100% sure, couldn't make sure with google, but it's just 2 threads trying to access the same memory: doesn't matter if they read or write, both will lead to errors.

Well I would appreciate you backing up a statement like that!
There are 2 threads here. One reads and writes (ie an addition), the other just reads. Two threads can indeed access the same memory quite happily (ok there might be some exceptions for custom embedded systems, but we're talking general purpose computers here). You have to remember that the operations in separate threads are not actually happening simultaneously, they are sequential at the hardware level and will not generate bad/corrupted data.
The write operation is atomic, you can't get half a write operation, so the read from the other thread will either get the value before or after the write. In this case it doesn't matter which it gets.
Of course, you do need to be aware of the operations you perform. Reading/writing a database in this way would not necessarily be atomic and possibly not safe.

commented: You were right. +1

Where would a good place be to learn more about multithreading? I don't think there is much at www.cpluplus.com. Any suggestions on libraries/tutorials? Thanks!

MrSpigot was 100% right, my bad. You don't need mutexes to write and read from one variable at the same time.

Tested with:

#include <iostream>
#include <windows.h>
using namespace std;

int victim = 10;

void thread()
{
    for(int n = 0; n < 99999999; n++){
        victim = n;
    }
}

int main()
{

    HANDLE thread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread, NULL, 0, NULL);
    HANDLE thread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread, NULL, 0, NULL);
    HANDLE thread3 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread, NULL, 0, NULL);

    WaitForSingleObject(thread1, INFINITE);
    WaitForSingleObject(thread2, INFINITE);
    WaitForSingleObject(thread3, INFINITE);
    return 0;
}

Well I would appreciate you backing up a statement like that!
There are 2 threads here. One reads and writes (ie an addition), the other just reads. Two threads can indeed access the same memory quite happily (ok there might be some exceptions for custom embedded systems, but we're talking general purpose computers here). You have to remember that the operations in separate threads are not actually happening simultaneously, they are sequential at the hardware level and will not generate bad/corrupted data.
The write operation is atomic, you can't get half a write operation, so the read from the other thread will either get the value before or after the write. In this case it doesn't matter which it gets.
Of course, you do need to be aware of the operations you perform. Reading/writing a database in this way would not necessarily be atomic and possibly not safe.

>You have to remember that the operations in separate threads are not actually happening simultaneously
It's a wrong statement even for home desktop compiters with multicore processors.
>...and will not generate bad/corrupted data
It's a wrong statetement, especially referred to compound objects.
>The write operation is atomic, you can't get half a write operation...
It's a wrong statement, especially for string data, but for compound objects too. As usually, regular microprocessors provide atomic write operations only for 32-bit aligned words.
>In this case it doesn't matter which it gets
It's a wrong statement. How about corrupted program logic and erratical behaviour?..
>Reading/writing a database in this way would not necessarily be atomic and possibly not safe.
Most of modern database engines provide implicit transactions on SQL statement level so possibly it would be atomic...

Hmm...

Okay, not 100% right. Darnit. xD

I've just created a single multithreaded program and it was (a dreaded task and) crashing constantly! So I ended up creating mutexes for every "group" of shared variables.

>You have to remember that the operations in separate threads are not actually happening simultaneously
It's a wrong statement even for home desktop compiters with multicore processors.
>...and will not generate bad/corrupted data
It's a wrong statetement, especially referred to compound objects.
>The write operation is atomic, you can't get half a write operation...
It's a wrong statement, especially for string data, but for compound objects too. As usually, regular microprocessors provide atomic write operations only for 32-bit aligned words.
>In this case it doesn't matter which it gets
It's a wrong statement. How about corrupted program logic and erratical behaviour?..
>Reading/writing a database in this way would not necessarily be atomic and possibly not safe.
Most of modern database engines provide implicit transactions on SQL statement level so possibly it would be atomic...

Hmm...

I accept all that you're saying there, and good point about the multi-core processors, though even they would not cause a problem in this case. Regards the other statements you highlighted, did I really need to qualify everything by saying it was in the context of this post? I thought it was clear enough that strings/compound objects/corrupt logic etc were not under discussion. If anyone thought I was writing more generally, thanks for setting them straight.

I accept all that you're saying there, and good point about the multi-core processors, though even they would not cause a problem in this case.

On my dualcore processor, 2 cores where in use and it indeed didn't give any errors as stated earlier. This is on Windows XP x64.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.