Jump to content

Is using variables in two different threads safe

Just as an example. If in c++ I have two methods. Both will run on separate threads. Both methods will be passed a pointer to a integer or other data type declared in the main method. The first method will do operations on and modify the value of the int. The second method will read but not write to the int. My question is if this is safe and whether it will behave as intended?

~ Luc Luc

Link to comment
Share on other sites

Link to post
Share on other sites

I would assume not unless you're locking the variable so that the 2nd thread can't read the variable while the variable is being written to.

CPU: Intel i7 - 5820k @ 4.5GHz, Cooler: Corsair H80i, Motherboard: MSI X99S Gaming 7, RAM: Corsair Vengeance LPX 32GB DDR4 2666MHz CL16,

GPU: ASUS GTX 980 Strix, Case: Corsair 900D, PSU: Corsair AX860i 860W, Keyboard: Logitech G19, Mouse: Corsair M95, Storage: Intel 730 Series 480GB SSD, WD 1.5TB Black

Display: BenQ XL2730Z 2560x1440 144Hz

Link to comment
Share on other sites

Link to post
Share on other sites

1 minute ago, trag1c said:

I would assume not unless you're locking the variable so that the 2nd thread can't read the variable while the variable is being written to.

Would there be a better solution to this?

~ Luc Luc

Link to comment
Share on other sites

Link to post
Share on other sites

7 minutes ago, Tornation said:

Would there be a better solution to this?

It depends on what you're doing. If your reading thread doesn't care that it might do an extra operation on a value that just changed, you don't need to do anything. If that does matter and you're only using basic types like int, you could look into using an atomic.

1474412270.2748842

Link to comment
Share on other sites

Link to post
Share on other sites

If the variable is not critical and the second thread is just there to monitor the data from the first, then you don't have to worry about thread-safe operations. However, if the data is critical, then you'll need some kind of lock (Mutex probably, sempahores may be overkill).

 

Alternatively you can use message passing/events if you have some subsystem built for it.

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, fizzlesticks said:

It depends on what you're doing. If your reading thread doesn't care that it might do an extra operation on a value that just changed, you don't need to do anything. If that does matter and you're only using basic types like int, you could look into using an array/vector of atomics.

In my case it would be ideally be a vector of POD objects (floats). I have to say I have never heard of atomics. I will look into it.

~ Luc Luc

Link to comment
Share on other sites

Link to post
Share on other sites

8 minutes ago, Tornation said:

In my case it would be ideally be a vector of POD objects (floats). I have to say I have never heard of atomics. I will look into it.

Unfortunately atomics won't work for anything besides integer types. So if any kind of synchronization is necessary you'll need to deal with locks. Condition variables might be some help though.

1474412270.2748842

Link to comment
Share on other sites

Link to post
Share on other sites

7 minutes ago, M.Yurizaki said:

Looks like http://en.cppreference.com/w/cpp/atomic/atomic is a good place to start.

 

But again, using this would depend on what you're doing with this data and how critical it is to the second thread.

std::atomic is a template struct though is it not? Would std::atomic<float> not work?

~ Luc Luc

Link to comment
Share on other sites

Link to post
Share on other sites

I'm not familiar with this module, but if you want me to dig further, I have to know exactly what you're doing with this data. Because the most important questions are: what is the second thread doing with this data and how critical is it?

Edited by M.Yurizaki
Module, not topic (I'm somewhat versed in threaded stuff)
Link to comment
Share on other sites

Link to post
Share on other sites

8 minutes ago, M.Yurizaki said:

I'm not familiar with this module, but if you want me to dig further, I have to know exactly what you're doing with this data. Because the most important questions are: what is the second thread doing with this data and how critical is it?

The second thread will be reading a set of floats that are to be used for model transformations in opengl. Basically a game thread and render thread scenario.

~ Luc Luc

Link to comment
Share on other sites

Link to post
Share on other sites

I believe what most games do is build up a list of things for the renderer to do and pass that as an object in the form of an event. The event itself has a copy of this data so thread safety is basically built-in.

 

Unless you're dealing with something that has very limited memory, I don't see this approach a problem.

Link to comment
Share on other sites

Link to post
Share on other sites

1 minute ago, M.Yurizaki said:

I believe what most games do is build up a list of things for the renderer to do and pass that as an object in the form of an event. The event itself has a copy of this data so thread safety is basically built-in.

 

Unless you're dealing with something that has very limited memory, I don't see this approach a problem.

Thank you for your help! I'm mainly just experimenting with things as I stubble through different documentation. :)

~ Luc Luc

Link to comment
Share on other sites

Link to post
Share on other sites

I think most software development has moved on from strict mutexes and semaphores and onto event passing because memory is plentiful and so you can have a copy of the data, rather than read the original variable and worry about if someone else tinkered with it.

 

As my last supervisor told me, if I'm resorting to locks, I'm probably doing it wrong.

Link to comment
Share on other sites

Link to post
Share on other sites

44 minutes ago, Tornation said:

std::atomic is a template struct though is it not? Would std::atomic<float> not work?

That depends on your compiler, the standard only specifies integral types. You would be able to store and load a float atomically but you wouldn't be able to do any math on it atomically which for most applications wouldn't make sense.

1474412270.2748842

Link to comment
Share on other sites

Link to post
Share on other sites

It seems like a bad idea to do what you want.

If the array contains non-basic datatypes you would need to lock the whole operation (writing function) object. In case of basic types you need to do the same unless the function only does one += or ++ operation, which can be handeled by atomics.

 

But that still wouldnt make the program deterministic because it doesnt garanty that reader thread is always behind the writer thread. Have a look at what real engines do, a lot of good videos/presentatioms are available at gdcvault.

 

There are two possible solutions: have two copies of all matrices and "lag" one frame behind. During frame n you calculate the matrices for frame n+1. This still requires synchronization so it isnt perse easy, especially if you want good load balancing.

 

A better solution is to build a low overhead task system that executes task graphs. You can then split the matrix operations in groups.

 

But since you dont seem to have any experience with parallel programming I would recommend you to look for some tutorials and explainations on Google (I dont know a good source as I learned it at university).

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×