About Multithreading and thread safe code

BlitzMax Forums/BlitzMax Programming/About Multithreading and thread safe code

-Phoenix-(Posted 2011) [#1]
Hello,
I've been working with blitzmax for a while and already wrote a share of multithreaded applications.

However a while ago I wanted to test what would happen if I let multiple threads access the same field of a type at the same time

I heard a lot about Deadlocking, Runtime errors caused by that, so I always used mutexes on global access variables.

But I was surprised that (on my quad core) when I had 20 threads running at same time without mutex/semaphore, increasing the same global variable by +1 as fast as possible, and even after letting it run for 10 minutes there was no crash.

However, I added a piece of code to let the threads report their value of the global variable each time they add 500.000 to it.

So logically it should display an ever increasing number, but it did not. Some threads reported a value lower than the previous thread, even though they reported later in time than the previous thread.
It was a long, there was no loop through reaching max value of the variable, it didn't even get close to the maximum value

So can I assume that blitzmax makes an internal copy of a global when it's accessed at the same time, to allow both having access without causing trouble?

Or is crashing through simultanious access really that hard to achieve? (CPU usage was 100%, means all cores were being used)

Last edited 2011


BladeRunner(Posted 2011) [#2]
I think it would be easier for us to follow with your code posted here. Maybe the problem lies in this piece of code.


-Phoenix-(Posted 2011) [#3]
Here's the code :

Strict

Type MyType

Field MyField:Long

End Type

Global Handle:MyType=New MyType

Function MyThread:Object( data:Object )
Local Number
Local ID=Rand(1000,9999)
Repeat
Number:+1
If Number=500000
Print "ID:"+ID+"="+Handle.MyField
Number=0
EndIf
Handle.MyField:+1
Forever

End Function

For Local x=0 To 19
CreateThread( MyThread,Null )
Next

Repeat
Handle.MyField:+1
Forever


Remember to put debug mode OFF

it might be hard to spot but here's an example of what I meant above :
Output :
[..]
ID:9924=54470329
ID:3485=55508678
ID:3485=55999886
ID:1778=55999345 <-- here, lower than the above!
ID:1778=56541196
ID:1189=56995827
[..]

Last edited 2011


Czar Flavius(Posted 2011) [#4]
You can put your code in [ code ] [ /code ] boxes to make it easier to read.

Two threads accessing the same variable doesn't mean an automatic crash, it just means the variable will change in a no longer predictable manner.


-Phoenix-(Posted 2011) [#5]
So you mean that simultaneous access itself cannot cause any crash? You just have to make sure that unpredictable changes don't make something happen that leads to a crash?


Czar Flavius(Posted 2011) [#6]
Yes.

Say you have a global variable to count the number of times you've completed an action, and the program exits when this reaches a certain number. A thread reads this value and increases it by 1. Two threads read the value at the same time and it is value 8. The first thread then writes 8+1=9. The second thread, which read at the same time, then writes 8+1=9. So the count variable is 9 even though two actions were performed and should be 10. This means in theory with two threads, you could perform twice as many actions as you wanted to.

At best, the program will just waste some time re-doing redundant actions, defeating the point of using two threads. Perhaps the program will exit cleanly but the end result is incorrect because the threads messed with each other's actions. At worst, the program could run out of resources by doing more actions than expected and crash.

This is why you use mutexes on resources and variables shared between threads. The two threads read at the same time. However, the mutex picks one to go first. This reads 8 and writes 8+1=9. Now the mutex lets the second thread have a go. It reads 9 and writes 9+1=10. There is a bit of a delay as the second thread is waiting for the first thread to finish with the variable, but then both threads can do their work on actions 8 and 9 respectively and simultaneously.

Last edited 2011


Kryzon(Posted 2011) [#7]
Nice explanation, thanks.