Qt objects - am I overusing QMutexLocker? - multithreading

I have a Qt object that's used by a GUI thread and a networking thread. It looks like:
QString User::Username()
{
QMutexLocker locker(&mutex);
return username;
}
void User::SetUsername(const QString &newUsername)
{
QMutexLocker locker(&mutex);
username = newUsername;
}
QString User::Password()
{
QMutexLocker locker(&mutex);
return password;
}
...
Both the GUI and networking thread may use the object (e.g. to display the username on the screen, and to get the username to send across the network).
I'm worried something is wrong, as every method in the object has a QMutexLocker line, to make it thread safe.
Is it acceptable to use QMutexLocker in this way, or is the code structured badly?

You should be using QReadWriteLock and QReadLocker or QWriteLocker respectively. So no threads will be locked if there are only reading threads.
If there are some fields of the class which are accessed changed very frequently, and which dont change any other state of the class, you might want to give it its own dedicated lock.

I think you may be going about things the wrong way. Serializing each method call will "sort of" work, but it won't reliably handle operations like adding or removing a User object. For example, if your main thread deletes the User object, it won't matter that the network thread is carefully locking a mutex, because after the mutex-lock operation returns, the network thread will then try to access the (now deleted) User object, and trying to read OR write freed memory will cause your app to crash (or worse, just mysteriously do the wrong thing sometimes).
Here's a better way to do it (assuming that the User objects are reasonably small): Instead of having the network thread and the I/O thread share the same User object, and trying to serialize all accesses to the object at the method level, you'd be better off giving a separate copy of each User object to the I/O thread. Then when one thread changes its local copy of the User object, it should send a message to the other thread containing a copy of the updated object, and when the other thread receives the message it can update its local copy to match again. That way each thread has exclusive read/write access to its own local set of User objects, and can read/write them without any locking. This also allows each thread to add or remove objects at will (as long as it sends an update-message to the other thread afterwards, so the other thread will follow suit).

I think a better and cleaner way would be to have a "safe section"
updateUser( User ) {
User.acquireLock()
User.SetUsername(newUsername)
User.Password()
< more operations here >
User.releaseLock()
}
The advantages of this is that you are locking only once the mutex( that is an expensive operation).

Related

Spawning a new thread for each object load

I have a system which runs multiple service (long lived) and worker (short lived) threads. They all share a state which contains objects. Any thread can request an object an any time, through a singleton-of-sorts class called ObjectManager. If the object is not available it needs to be loaded.
Here's some pseudo-code of how object loading looks now:
class ObjectManager {
getLoadinData(path) {
if (hasLoadingDataFor(path))
return whatWeHave()
else {
loadingData = createNewLoadingData();
loadingData.path = path;
pushLoadingTaskToLoadingThread(loadingData);
return loadingData;
}
}
// loads object and blocks until it's loaded
loadObjectSync(path) {
loadingData = getLoadinData(path);
waitFor(loadingData.conditionVar);
return loadingData.loadedObject;
}
// initiates a load and calls a callback when done
loadObjectAsync(path, callback) {
loadingData = getLoadinData(path);
loadingData.callbacks.add(callback);
}
// dedicated loading thread
loadingThread() {
while (running) {
loadingData = waitForLoadingData();
object = readObjectFromDisk(loadingData.path);
object.onLoaded(); // !!!!
loadingData.object = object;
// unblock cv waiters
loadingData.conditionVar.notifyAll();
// call callbacks
loadingData.callbacks.callAll(object);
}
}
}
The problem is the line object.onLoaded. I have no control over this function. Some objects might decide that they need other objects to be valid. So in their onLoaded method they might call loadObjectSync. Uh-oh! This (naturally) dead locks. It blocks the loading loop until the loading loop makes more iterations.
What I could do to solve this is leave the onLoaded call to the initiating threads. This will change loadObjectSync to something like:
loadObjectSync(path) {
loadingData = getLoadinData(path);
waitFor(loadingData.conditionVar);
if (loadingData.wasCreatedInThisThread()) {
object.onLoaded();
loadingData.onLoadedConditionVar.notifyAll();
loadingData.callbacks.callAll(object);
}
else {
// wait more
waitFor(loadingData.onLoadedConditionVar);
}
return loadingData.loadedObject;
}
... but then the problem is that if I have no calls for loadSync and only for loadAsync or simply the loadAsync call was the first to create the loading data, there will be no one to finalize the object. So to make this work, I have to introduce another thread finalizes objects whose loadingData was created by loadObjectAsync.
It seems that it would work. But I have a simpler idea! What if I change getLoadingData instead. What if it does this:
getLoadinData(path) {
if (hasLoadingDataFor(path))
return whatWeHave()
else {
loadingData = createNewLoadingData();
loadingData.path = path;
///
thread = spawnLoadingThread(loadingData);
thread.detach();
///
return loadingData;
}
}
Spawn a new thread for every object load. Thus there is no dead lock. Every loading thread can safely block until it's done. The rest of the code remains exactly as it is.
This means potentially tens (or why not thousands in certain edge cases) active threads, waiting on condition variables. I know that spawning threads has its overhead but I think it would be negligible compared to the cost of I/O from readObjectFromDisk
So my question is: Is this terrible? Can this somehow backfire?
The target platform is conventional desktop machines. But this software is supposed to run for a long time without stopping: weeks, maybe months.
Alternatively... even though I have an idea how to solve this if the thread-per-load turns out to be terrible, can this be solved in another way?
Very interesting! This is a problem I have bumped into a couple of times, trying to add a synchronous interface to a fundamentally asynchronous operation (i.e. file load, or in my case, network write) that is performed by a service thread.
My own preference would be to not provide the synchronous interface. Why? Because it keeps the code simpler in design & implementation and easier to reason about -- always important for multi-threading.
Benefits of sticking to single thread & async only is that you only have 1 service thread, so resource growth is not a concern, plus the user callbacks are always invoked on this same thread, which simplifies thread-safety concerns for users of ObjectManager (if you have multiple callback threads, every user callback must be thread safe, so it's an important choice to make). However sticking to only an async interface does mean the user of ObjectManager has more work to do.
But if you do want to keep the synchronous interface, then another approach that I have taken could work for you. You stick to a single service thread but inside the implementation of loadObjectSync you check the thread-ID to determine if the invoker is the service thread or any-other thread. If it is any-other thread you queue the request and safely block. But if it is the service thread, you can immediately load the object, say by calling a new function loadObjectImpl. You will need to grab the thread-ID of the service thread during initialization and store it within the ObjectManager instance, and use that for thread identification. And you will need a new function which is basically just the internal scope of the loadingThread function -- i.e. a new function called something like loadObjectImpl.

Synchronizing data access in different threads

I have a worker thread, which sends some data over TCP, taking that data from several other threads. I need to fill some data, having sort of a mutex over it, and then call another thread's method, which would then unlock the mutex when finished while caller thread would continue its own job.
I've first implemented this using Qt as follows:
Data globalData;
QMutex mutex;
void requestSend() // several such functions in other threads
{
mutex.lock(); // we want to change the data
globalData=fillData();
invokeMethod(workerClass,"work",Qt::QueuedConnection);
}
void work() // a slot in a class instanced in worker thread
{
sendData(globalData);
mutex.unlock(); // data is now available to be changed
}
This seems reasonable and even works, but then I found this in the QMutex documentation:
void QMutex::unlock ()
Unlocks the mutex. Attempting to unlock a mutex in a different thread to the one that locked
it results in an error. Unlocking a mutex that is not locked results in undefined behavior.
I have two questions:
What's the reason of such restriction to unlock in a different thread? (and why don't I see the error the doc says about?)
What should I use instead of QMutex to achieve what I'm trying to? Would QWaitCondition be an adequate replacement?
The purpose of the mutex is to ensure that only one thread can access the data at any one time. Therefore, it doesn't really make sense to lock in one thread and unlock the same mutex in another.
If you're finding it works, you're probably just lucky at the moment, but doesn't mean it won't cause you issues if the timing of threads changes.
I'm not quite sure exactly what you're trying to do, but it appears that you have various threads that can write to the globalData and as soon as you write to it, you want another thread to send the data before more data writes to the globalData.
What I suggest is to create a mutex around the writing of the data and just call a signal to send the data to the thread that will send the data. Being on different threads, the data will be copied anyway: -
void requestSend() // several such functions in other threads
{
QMutexLocker locker(&mutex);
globalData=fillData();
emit SendData(globalData); // send signal to the thread which will send the data
}
Note that QMutexLocker is used to ensure the lock is released, even if an exception should occur.
Don't be too concerned about the copying of data in signals and slots; Qt is very efficient, and will only create a "copy on write", due to implicit sharing, if you use its container objects. Even if it has to make the copy for passing the data between the threads, you shouldn't really worry about it, unless you can see a performance issue.
Finally, note that implicit sharing and multithreading can work happily together, as you can read here.

Need to lock a copy of an stl::map of pointers while reading?

I have an stl::map<int, *msg> msg_container, where msg is a class (not relevant here).
There are multiple threads adding to the global msg_container, with locks in place for synchronised access.
In a seperate thread, it needs to assess a local copy of msg_container at a particular time and perform checks on it. Pseudo-code as below
map<int, *msg> msg_container;
map<int, *msg> msg_container_copy;
if (appropriate_time_is_reached)
{
msg_container_copy = msg_container;
//perform functions on msg_container_copy
}
As per my previous question, I know I will need to lock msg_container when reading, if there is a chance that other threads are adding to it.
Do I need to lock msg_container_copy when using it in this manner? It is local only to this thread, so there are no other threads that will be accessing it.
I do not see the necessity to lock the variable msg_container_copy if as you describe, "It is local only to this thread, so there are no other threads that will be accessing it."
By the way, I think the definition "stl::map<int, *msg> msg_container;" should be written as "stl::map<int, msg *> msg_container;" if msg is a class, so that msg * is a pointer type. It must be a typo.
You don't need a lock to access msg_container_copy because no other thread can access it.
You might need a lock when dereferencing the pointers it contains, because they are shared with other threads. It depends what you do with those pointers.

are class level property or variables thread safe

I always had this specific scenario worry me for eons. Let's say my class looks like this
public class Person {
public Address Address{get;set;}
public string someMethod()
{}
}
My question is, I was told by my fellow developers that the Address propery of type Address, is not thread safe.
From a web request perspective, every request is run on a separate thread and every time
the thread processes the following line in my business object or code behind, example
var p = new Person();
it creates a new instance of Person object on heap and so the instance is accessed by the requesting thread, unless and otherwise I spawn multiple threads in my application.
If I am wrong, please explain to me why I am wrong and why the public property (Address) is not thread safe?
Any help will be much appreciated.
Thanks.
If the reference to your Person instance is shared among multiple threads then multiple threads could potentially change Address causing a race condition. However unless you are holding that reference in a static field or in Session (some sort of globally accessible place) then you don't have anything to be worried about.
If you are creating references to objects in your code like you have show above (var p = new Person();) then you are perfectly thread safe as other threads will not be able to access the reference to these objects without resorting to nasty and malicious tricks.
Your property is not thread safe, because you have no locking to prevent multiple writes to the property stepping on each others toes.
However, in your scenario where you are not sharing an instance of your class between multiple threads, the property doesn't need to be thread safe.
Objects that are shared between multiple threads, where each thread can change the state of the object, then all state changes need to be protected so that only one thread at a time can modify the object.
You should be fine with this, however there are a few things I'd worry about...
If your Person object was to be modified or held some disposable resources, you could potentially find that one of the threads will be unable to read this variable. To prevent this, you will need to lock the object before read/writing it to ensure it won't be trampled on by other threads. The easiest way is by using the lock{} construct.

Is there a way to detect if an object is locked?

Is there any way to determine if an object is locked in C#? I have the unenviable position, through design where I'm reading from a queue inside a class, and I need to dump the contents into a collection in the class. But that collection is also read/write from an interface outside the class. So obviously there may be a case when the collection is being written to, as the same time I want to write to it.
I could program round it, say using delegate but it would be ugly.
You can always call the static TryEnter method on the Monitor class using a value of 0 for the value to wait. If it is locked, then the call will return false.
However, the problem here is that you need to make sure that the list that you are trying to synchronize access to is being locked on itself in order to synchronize access.
It's generally bad practice to use the object that access is being synchronized as the object to lock on (exposing too much of the internal details of an object).
Remember, the lock could be on anything else, so just calling this on that list is pointless unless you are sure that list is what is being locked on.
Monitor.TryEnter will succeed if the object isn't locked, and will return false if at this very moment, the object is locked. However, note that there's an implicit race here: the instance this method returns, the object may not be locked any more.
I'm not sure if a static call to TryEnter with a time of 0 will guarantee that the lock will not be acquired if it is available. The solution I did to test in debug mode that the sync variable was locked was using the following:
#if DEBUG
// Make sure we're inside a lock of the SyncRoot by trying to lock it.
// If we're able to lock it, that means that it wasn't locked in the first
// place. Afterwards, we release the lock if we had obtained it.
bool acquired = false;
try
{
acquired = Monitor.TryEnter(SyncRoot);
}
finally
{
if (acquired)
{
Monitor.Exit(SyncRoot);
}
}
Debug.Assert(acquired == false, "The SyncRoot is not locked.");
#endif
Monitor.IsEntered
Determines whether the current thread holds the lock on the specified object.
Available since 4.5
Currently you may call Monitor.TryEnter to inspect whether object is locked or not.
In .NET 4.0 CLR team is going to add "Lock inspection API"
Here is a quotation from Rick Byers article:
lock inspection
We're adding some simple APIs to ICorDebug which allow you to explore managed locks (Monitors). For example, if a thread is blocked waiting for a lock, you can find what other thread is currently holding the lock (and if there is a time-out).
So, with this API you will be able to check:
1) What object is holding a lock?
2) Who’s waiting for it?
Hope this helps.

Resources