Lock to create threadafe class with C # example or is it threadsafe class?

I am trying to investigate the lock to create a threadafe class and ask a couple of questions. Given the following class:

public class StringMe { protected ArrayList _stringArrayList = new ArrayList(); static readonly object _locker = new object(); public void AddString(string stringToAdd) { lock (_locker) _stringArrayList.Add(stringToAdd); } public override string ToString() { lock (_locker) { return string.Join(",",string[])_stringArrayList.ToArray(Type.GetType("System.String"))); } } } 

1) Did AddString and ToString succeed in making thread safe?

2) In the ToString method that I created, do I need to lock it to make it thread safe?

3) Are there only methods that modify data that needs to be locked, or so that read and write locks are locked to make them thread safe?

Thank you so much for your time!

+4
source share
3 answers

No, you did not make these calls thread safe - because the _stringArrayList field _stringArrayList protected. Subclasses could do whatever they like with them while AddString and ToString called.

For example (since other answers claim your code is thread safe.)

 public class BadStringMe : StringMe { public void FurtleWithList() { while (true) { _stringArrayList.Add("Eek!"); _stringArrayList.Clear(); } } } 

Then:

 BadStringMe bad = new BadStringMe(); new Thread(bad.FurtleWithList).Start(); bad.AddString("This isn't thread-safe"); 

Prefer private fields - this makes it easier to explain your code.

Additionally:

  • Prefer List<T> - ArrayList these days
  • For some reason you are blocking a static variable ... so even if you have multiple instances of StringMe , only one thread can be in AddString at a time in total
  • Using typeof(string) much cleaner than Type.GetType("System.String")

3) Are there only methods that modify data that needs to be locked, or so that read and write locks are locked to make them thread safe?

All if we assume that there may be some operations. If everything is just reading, you do not need locks, but otherwise your reading streams could read two bits of data from the data structure that were changed between them, even if there is only one stream of letters. (There are also memory model considerations to keep in mind.)

+13
source

1) Did AddString and ToString succeed in making thread safe?

Yes, if you change _stringArrayList to personal

2) In the ToString method that I created, do I need to lock it to make it streaming?

Yes

3) Are there only methods that modify data that needs to be locked, or so that read and write locks are locked to make them thread safe?

Reading and writing.

+4
source

Yes to all three (i.e. read / write to the last).

But there is also:

You create a static lock object, while the data you protect is a field for each instance. This means that all instances of StringMe are protected from each other by events, although they have different data (i.e. _stringArrayList instances). In the above example, you can remove the static modifier with _locker . To be more precise, you usually define a “lock” for the data set or, even better, the invariants that you want to keep. Typically, the lifetime (and scope) of a lock should match the lifetime.

In addition, for a good assessment, you should not have a higher visibility of the protected data than from blocking. In your example, a derived implementation can change _stringArrayList (since it is protected) without acquiring a lock, thereby violating the invariant. I would make them private , and, if necessary, set _stringArrayList via (appropriately locking) methods to derived classes.

+3
source

Source: https://habr.com/ru/post/1391859/


All Articles