2

I have seen a lot of questions asked about static methods being accessed by multiple threads and the thread-safety of them. I think I have got most of it down in terms of ensuring thread safety, but one thing I am not too sure about is when you introduction the 'ref' variable into the mix within the static method itself. Here is a cut down example:

public static string ProcessMessage(object msg)
{

string outcome = "";

Decrypt(ref msg);

// parse msg

return outcome;

}

private static void Decrypt(ref object msg)
{

// decrypt msg

}

Is the above example thread-safe? All the processing that takes place within the static methods uses locally declared variables, it's just the ref object that gets passed from one static method to another that I'm unsure about.

Tigran
  • 61,654
  • 8
  • 86
  • 123
ChrisMC
  • 21
  • 1
  • IMHO, all code is thread-safe, (unless self-modifying - ugh!), so it's down to the data. If there are only auto-storage variables on the calling stack, I don't see why it would not be thread-safe, but I will see what the other posters say - I'm not giving an answer myself yet! – Martin James Apr 16 '12 at 10:52
  • Ok, so I think from reading all the responses that I have got it sorted in my head. There has been some good discussion on Threading as a whole and it has re-enforced how careful you need to be when objects are involved. Just not too sure which answer to select, as I have taken good points of view from them all! – ChrisMC Apr 16 '12 at 12:27

3 Answers3

1

It's not about static or not, it's about how the data operated by those methods is isolated.

If you operate on reference types, it's not thread-safe as is it presented in the code in both examples.

You need to you use some locking mechanism to ensure thread-safity.

Tigran
  • 61,654
  • 8
  • 86
  • 123
  • Could you please explain why it is not safe? I don't understand - there is no static data. I quite often pass reference/pointer types into static functions - seems to work fine for me. – Martin James Apr 16 '12 at 10:49
  • as it is passed like a *reference* there is no any guarantee that during the access to it read/write someone else outside of scope of the given function will not be able to change it's properties/state. – Tigran Apr 16 '12 at 10:50
  • But surely, that applies to any function? If you pass in some object by reference/pointer and some other thread alters the objects fields, then sure, the fields will get changed by multiple threads. But that is expanding the scope of the OP question to a level that is difficult to justify. If many threads want to use this static, (or any fuction like this), they must pass in different objects! Passing in the same object is a problem with the caller, not with the OP code as presented. – Martin James Apr 16 '12 at 10:57
  • Well I'm responding to the question. I can not deduct how the given methods would be used. So on the question is the provided code thread-safe, I say *no*, it's not thread-safe. After you can construct over it a complete thread-safe structure, that locks/isoltaes the data, so ensures that data which is passed inside those methods has never collision, but it's architectual choice and by the way, the *given methods* remain to be not thread-safe. – Tigran Apr 16 '12 at 11:06
  • Thanks for all the responses. Trying to tie this down, if nothing is 'operating' on the msg object outside of these methods, and each thread is passing in their own msg object in the call to ProcessMessage, would that be considered thread-safe? – ChrisMC Apr 16 '12 at 11:32
  • @ChrisMC yes. One alternative is a static mutex on any method that takes a ref or pointer object parameter. You can then say with absolute certainty that your app is 100% thread-safe, though you won't be able to sell any because of the apalling performance and continual deadlocks. – Martin James Apr 16 '12 at 11:38
0

It seems to me that it's thread-safe within itself but, of course, there is nothing stopping external factors doing odd stuff, like multiple threads calling in with the same reference. Some developers say this can be thread-unsafe. It could be if the common object contains thread-unsafe member data or methods that can reach such data, but this is taking your question a bit to extremes, to me.

Perhaps it's just me?

It would seem that almost every function/procedure I have written for the last 30 years is not thread-safe, especially the ones that work in multithreaded apps.

Martin James
  • 24,453
  • 3
  • 36
  • 60
0

Your code looks like it doesn't need the ref parameter at all.

You can change it like this to ensure safety:

public static string ProcessMessage(object msg)
{

string outcome = "";

object decryptedMsg = Decrypt(msg);    

// parse decryptedMsg

return outcome;

}

private static object Decrypt(object msg)
{
object processedMsg;

// decrypt msg into processedMsg

return processedMsg;

}

since Decrypt is private, and msg is an object, I would assume this code to be safe while achieving the same result as your code.

Alex
  • 23,004
  • 4
  • 39
  • 73
  • Hmm.. does that not involve a bit of copying? What happens if msg. contains a 10GB buffer? – Martin James Apr 16 '12 at 11:26
  • Well, question was about thread-safety ... ProcessMessage() method is already copying data around (multiple threads are calling it, if I understand the question correctly) so I'd assume it's reasonably small sized. Anyway, an object *that* big would almost require heavy yielding imho (i think no one would even hope to process 10GB of data as a whole in a useful amount of time) – Alex Apr 16 '12 at 11:42
  • ProcessMessage is not copying data around if it takes a ref or pointer parameter, surely? Not sure what you mean about the yielding. Pesumably, operating on that much data would take some time, but so what? If it was me, I would be assembling the result string in a string member of the object passed in by ref, so eliminating the stack string entirely. I mean, if you're going to pass in an objet by reference, why not just shove any results into its fields before returning. It's efficient and will AV/segfalt quick if some drunk coder calls in with the same object from multiple threads. – Martin James Apr 16 '12 at 11:57
  • Uhm of course it is, it's not passed in by ref... Again, the question was "is this safe?" not "is this optimal for any possibly conceivable situation in the galaxy?" :) We can argue about optimization till the end of time and still disagree about some aspects :) – Alex Apr 16 '12 at 12:04
  • Sorry - I was thinking about the OP post where one of the options is to pass i a ref. My mistake :( – Martin James Apr 16 '12 at 12:09