What Makes a Method Thread-Safe? What Are the Rules

What Makes a Method Thread-safe? What are the rules?

If a method (instance or static) only references variables scoped within that method then it is thread safe because each thread has its own stack:

In this instance, multiple threads could call ThreadSafeMethod concurrently without issue.

public class Thing
{
public int ThreadSafeMethod(string parameter1)
{
int number; // each thread will have its own variable for number.
number = parameter1.Length;
return number;
}
}

This is also true if the method calls other class method which only reference locally scoped variables:

public class Thing
{
public int ThreadSafeMethod(string parameter1)
{
int number;
number = this.GetLength(parameter1);
return number;
}

private int GetLength(string value)
{
int length = value.Length;
return length;
}
}

If a method accesses any (object state) properties or fields (instance or static) then you need to use locks to ensure that the values are not modified by a different thread:

public class Thing
{
private string someValue; // all threads will read and write to this same field value

public int NonThreadSafeMethod(string parameter1)
{
this.someValue = parameter1;

int number;

// Since access to someValue is not synchronised by the class, a separate thread
// could have changed its value between this thread setting its value at the start
// of the method and this line reading its value.
number = this.someValue.Length;
return number;
}
}

You should be aware that any parameters passed in to the method which are not either a struct or immutable could be mutated by another thread outside the scope of the method.

To ensure proper concurrency you need to use locking.

for further information see lock statement C# reference and ReadWriterLockSlim.

lock is mostly useful for providing one at a time functionality,

ReadWriterLockSlim is useful if you need multiple readers and single writers.

How to know if a method is thread safe

This is a how long is a piece of string question...

A method will be thread safe if it uses the synchronized keyword in its declaration.

However, even if your setId and getId methods used synchronized keyword, your process of setting the id (if it has not been previously initialized) above is not. .. but even then there is an "it depends" aspect to the question. If it is impossible for two threads to ever get the same object with an uninitialised id then you are thread safe because you would never be attempting to concurrently modifying the id.

It is entirely possible, given the code in your question, that there could be two calls to the thread safe getid at the same time for the same object. One by one they get the return value (null) and immediately get pre-empted to let the other thread run. This means both will then run the thread safe setId method - again one by one.

You could declare the whole save method as synchronized, but if you do that the entire method will be single threaded which defeats the purpose of using threads in the first place. You tend to want to minimize the synchronized code to the bare minimum to maximize concurrency.

You could also put a synchronized block around the critical if statement and minimise the single threaded part of the processing, but then you would also need to be careful if there were other parts of the code that might also set the Id if it wasn't previously initialized.

Another possibility which has various pros and cons is to put the initialization of the Id into the get method and make that method synchronized, or simply assign the Id when the object is created in the constructor.

I hope this helps...

Edit...
The above talks about java language features. A few people mentioned facilities in the java class libraries (e.g. java.util.concurrent) which also provide support for concurrency. So that is a good add on, but there are also whole packages which address the concurrency and other related parallel programming paradigms (e.g. parallelism) in various ways.

To complete the list I would add tools such as Akka and Cats-effect (concurrency) and more.

Not to mention the books and courses devoted to the subject.

I just reread your question and noted that you are asking about databases. Again the answer is it depends. Rdbms' usually let you do this type of operation with record locks usually in a transaction. Some (like teradata) use special clauses such as locking row for write select * from some table where pi_cols = 'somevalues' which locks the rowhash to you until you update it or certain other conditions. This is known as pessimistic locking.

Others (notebly nosql) have optimistic locking. This is when you read the record (like you are implying with getid) there is no opportunity to lock the record. Then you do a conditional update. The conditional update is sort of like this: write the id as x provided that when you try to do so the Id is still null (or whatever the value was when you checked). These types of operations are usually down through an API.

You can also do optimistics locking in an RDBMs as follows:
SQL
Update tbl
Set x = 'some value',
Last_update_timestamp = current_timestamp()
Where x = bull AND last_update_timestamp = 'same value as when I last checked'

In this example the second part of the where clause is the critical bit which basically says "only update the record if no one else did and I trust that everyone else will update the last update to when they do". The "trust" bit can sometimes be replaced by triggers.

These types of database operations (if available) are guaranteed by the database engine to be "thread safe".

Which loops me back to the "how long is a piece of string" observation at the beginning of this answer...

How to write thread-safe methods?

I believe you may mean something different by thread-safety than the usual definition of the term. The normal meaning of the term is that the same method or object may be called by multiple threads simultaneously without errors or negative side effects. Typically, that kind of thread-safety is accomplished via statelessness and locking (e.g. SyncLock).

However, in your example, the code is not attempting to provide that kind of thread-safety, or at least not directly. It does accomplish that kind of thread-safety, but only by forcing all invocations to be executed on the same single thread (the UI thread). WinForm applications (which I presume this is) require that all UI work is done on the UI thread. Therefore, if a method which does something with the UI is called from another thread, it must first invoke back to the UI thread before completing its work. For that specific scenario, the code you have posted is fine.

Static or Non Static methods, thread safety is for the types not methods

are static method implementation threads safe?

No, if they modify shared data, then they are just as non-thread safe. Your example could be OK but only because the shared data is threadsafe itself being a ConcurrentDictionary of immutable types (ints).

instance methods are certainly thread safe, if we assign a separate instance to each thread

Well no, if an instance is accessed by a single thread then that doesn't make it threadsafe. That's just avoiding multi-thread issues.

In short static has nothing to do with multi-threading.

How to ensure thread safety of utility static method?

It is well known that static methods with immutable objects as parameters are thread safe and mutable objects are not.

I would contest this. Arguments passed to a method are stored on a stack, which is a per-thread idiom.

If your parameter is a mutable object such as a Date then you need to ensure other threads are not modifying it at the same time elsewhere. But that's a different matter unrelated to the thread-safety of your method.

The method you posted is thread-safe. It maintains no state and operates only on its arguments.

I would strongly recommend you read Java Concurrency in Practice, or a similar book dedicated to thread safety in Java. It's a complex subject that cannot be addressed appropriately through a few StackOverflow answers.

Which features make a class to be thread-safe?

A class is generally considered thread-safe if its methods can be invoked by multiple threads concurrently without corrupting the state of the class or causing unexpected side-effects. There are many reasons why a class may not be thread safe, although some common reasons are that it contains some state that would be corrupted on concurrent access.

There are a number of ways to make a class thread-safe:

  1. Make it immutable, if a class contains no state it is safe to use concurrently from multiple threads.
  2. Employ locking to reduce concurrency. However, this is no guarantee of thread safety, it just ensures that a block of code will not be executed concurrently by multiple threads. If state is stored between method invocations this might still become inconsistent.

How you create a thread-safe class really depends on what you want to do with the class in question.

You also need to ask yourself, do I need to make my class threadsafe? a common model of most UI frameworks is that there is a single UI thread. For example in WinForms, WPF and Silverlight the majority of your code will be executed from the UI thread which means you do not have to build thread-safety into your classes.

What do the terms synchronized and thread-safe mean?

A thread is an execution path of a program. A single threaded program will only have one thread and so this problem doesn't arise. Virtually all GUI programs have multiple execution path and hence threads - one for processing the display of the GUI and handing user input, others for actually performing the operations of the program. This is so that the UI is still responsive while the program is working.

In the simplest of terms threadsafe means that it is safe to be accessed from multiple threads. When you are using multiple threads in a program and they are each attempting to access a common data structure or location in memory several bad things can happen. So, you add some extra code to prevent those bad things. For example, if two people were writing the same document at the same time, the second person to save will overwrite the work of the first person. To make it thread safe then, you have to force person 1 to wait for person 2 to complete their task before allowing person 1 to edit the document.

Synchronized means that in a multiple threaded environment, a Synchronizedobject does not let two threads access a method/block of code at the same time. This means that one thread can't be reading while another updates it.

The second thread will instead wait until the first is done. The overhead is speed, but the advantage is guaranteed consistency of data.

If your application is single threaded though, Synchronized has no benefit.

Thread safety and local variables

i is declared as a local (method) variable, so it only normally exists in the stack-frame of Increment() - so yes, i is thread safe... (although I can't comment on getFromDb).

except if:

  • Increment is an iterator block (i.e. uses yield return or yield break)
  • i is used in an anonymous method ( delegate { i = i + 1;} ) or lambda (foo => {i=i+foo;}

In the above two scenarios, there are some cases when it can be exposed outside the stack. But I doubt you are doing either.

Note that fields (variables on the class) are not thread-safe, as they are trivially exposed to other threads. This is even more noticeable with static fields, since all threads automatically share the same field (except for thread-static fields).



Related Topics



Leave a reply



Submit