Multithreading using <thread>

Ok so what I'm trying to do is see how many times a number of threads can run a function in one second.

So I want to create 1, 2, 4, 8 and 16 threads, count the number of times a function run by those threads in one second, and output the number of functions calls aswell as number of threads to the console.

I've never done threading in C++ before so not really sure how the syntax is supposed to work, I can get one thread working, but after that I'm at a loss. So any help would be great.

So this is the function which I want the threads to call, it works fine if I just call it once within the main.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void moneyTransfer(Bank* bank)
{
	int account1 = (rand()%bank->numAccounts) + 90000000;
	int account2 = (rand()%bank->numAccounts) + 90000000;
	int transferAmount = (rand()%10000);
	int balanceBefore = bank->bankBal;
	int balanceAfter;

	bank->transfer(account1, account2, transferAmount);

	balanceAfter = bank->bankBal;

	if(balanceAfter != balanceBefore)
		cout << "Error! Bank balance changed." << endl;

	numTransfers ++;
}


All I have with regards to threads so far is:

1
2
3
4
5
6
7
8
9
10
11
12
#include <thread>

int main()
{
...
thread one(moneyTransfer, bank0acc);
one.join();
Sleep(1000);
cout << "Transfers with one thread: " << numTransfers << endl;
...
}


But that only calls itself once?
Last edited on
The function you pass to std::thread's constructor is like that thread's 'main'. It runs exactly once... and when it returns, the thread shuts down. So if you want it to run something multiple times, you will need to put it in a loop.

Also note that one.join(); will have this thread wait until the one thread closes on its own. It will NOT force it to close. So if moneyTransfer is in an infinite loop and you try to join() with it, your program will deadlock.

Typically, when you want a thread to close... you set some kind of flag in the main thread to indicate the sub thread should close, then you join(). And in the subthread, you periodically check that flag to see if the thread should resume or not. If the flag indicates the thread should shut down, you return out of the function.


But there's an even bigger problem here.

You're not doing any synchronization. If this 'bank' object is going to be accessed by multiple threads simultaneously... you will need to synchronize accesses to it. This is typically done with a mutex (ie: locking the mutex when you start a read/write of the bank data, and unlock when you're done).

This ensures that other threads trying to access the objects will wait until your thread is done (only one thread can have a mutex locked at a time).

It also slows things way down because multiple threads will be butting heads trying to access the same object... most of their time will be wasted on waiting for other threads to finish with their accesses.

But even though it slows it down, it is absolutely necessary. Failure to do it will result in your program doing extremely weird things (variables getting corrupted mid-write.. trying to read variables gets you the wrong data, possibly even program crashes).


So really... this particular instance of what you're trying to do looks to be a bad use of multithreading. Having 16 threads trying to access and manipulate the same object at the same time is going to be slow. It might even be slower than doing it in a single thread.
I think I've already dealt with the second problem there, I have an InterlockedExchangeAdd function within my bank object's transaction method which I've been told solves that problem?

So assuming that that's fine (although feel free to correct me if it's not), with regards to calling the single thread multiple times, should the loop go in the 'main' of the entire program? Or within the actual function being passed to the thread?

How do I shut down a thread then once it's running but I want it to stop?

I would presume what I'd be looking for is something along the lines of:

1
2
3
4
5
while(!close)
{
     one.join();
}
one.finish();


and then somewhere in my main have
1
2
Sleep(1000);
close = true;



Also I think the reason for using this multithreading is just to show us how additional threads effects processing speed.

Edit: Although the likelihood of them accessing the same variables is quite slim, there's a couple of thousand variables and each function call will pick a random one of them :)
Last edited on
So assuming that that's fine (although feel free to correct me if it's not), with regards to calling the single thread multiple times, should the loop go in the 'main' of the entire program? Or within the actual function being passed to the thread?


If you were to insert a loop inside your "'main' of the entire program" you would start your thread in each iteration.
Starting a thread takes time. Depending on what the thread is supposed to do it might not even be worth it.
=> start the Thread once and make a loop inside the Thread function

I've only once used the <thread> lib so I guess it's better Disch explains everything else.
(Don't use some kind of .terminate() to stop the Thread that's not cool ^.^)
Last edited on
So assuming that that's fine (although feel free to correct me if it's not), with regards to calling the single thread multiple times, should the loop go in the 'main' of the entire program? Or within the actual function being passed to the thread?


Launch secondary threads from the main thread. If you think about this one for a moment, it's kind of obvious.

How do I shut down a thread then once it's running but I want it to stop?


Pass a pointer to a the same Boolean variable to each thread. Then have the thread function check it at each pass. When you want to quit, flip the Boolean and you're done.
Last edited on
I have an InterlockedExchangeAdd function within my bank object's transaction method which I've been told solves that problem?


It's impossible for me to say whether or not it addresses the problem without seeing that function, but based on what I'm seeing in this code... I highly doubt it does.

In fact, I see you doing this in the support thread:

1
2
	int account1 = (rand()%bank->numAccounts) + 90000000;
	int account2 = (rand()%bank->numAccounts) + 90000000;


numAccounts is a member of the bank object, which is being shared across multiple threads. Reading these variables without any guard (as you are doing) is ok only if no other thread will be writing to them. If any thread will be writing to them, then all reads and writes need to be guarded.

You do similar reads with bankBal.

Additionally...
numTransfers ++;

This is a read+write... so if multiple threads are accessing the same 'numTransfers' var (ie: if it's global, which it appears to be), then this also needs to be protected.


How do I shut down a thread then once it's running but I want it to stop?


You return out of the thread's function. Once that function exits the thread stops.

I would presume what I'd be looking for is something along the lines of:
1
2
3
4
5
while(!close)
{
     one.join();
}
one.finish();


You do not want to put this inside of thread 'one'. one.join() tells the current thread to wait for 'one' to finish. If you call that from within the 'one' thread... it'll either deadlock (the thread is waiting for itself to finish) or it'll have some other equally terrible behavior.

It's actually pretty simple:

1
2
3
4
5
6
7
8
9
void yourThreadHandler()  // <- the function called for this thread
{
    while(running)  // <- (this is a bad example... see below)
    {
        // do thread work
    }
    // as soon as 'running' is false, the loop exits and the function returns
    //   so this thread = closed.
}


But of course... it's not as simple as while(running) because 'running' has to be a variable shared between multiple threads, which means it needs to be guarded.

The two common ways to do this are:

1) Put accesses behind a mutex (see the <mutex> header)
or
2) Make it atomic (see the <atomic> header)


I'm not going to get into details of these as this is quite a large topic. I will say that multithreading in C++ is definitely not a "beginner" task because it's very easy to get wrong... and when it goes wrong, it's very hard to find and fix the bugs.



Also I think the reason for using this multithreading is just to show us how additional threads effects processing speed.


Ack... is this a school assignment? *shudder*

Edit: Although the likelihood of them accessing the same variables is quite slim, there's a couple of thousand variables and each function call will pick a random one of them :)


Maybe so. But that's exactly why thread-safety bugs are so hard to find and fix: Your program works just fine 95% of the time... except for the 5% of the time where it does really weird crap and you have no idea why.
Topic archived. No new replies allowed.