1

The lock keyword is used where you want to achieve that the area should be executed by at most on thread, in a multithreading environment, rest of the thread will wait for the area.

I have a collection IList<Student> student=new List<Student>() that is being used in multiple classes.

In some places objects are getting added to the list, and in some places objects are getting deleted. This causes some inconsistent behavior.

Is it true that when I lock the collection in class x in a multithreading environment, the collection will be locked for all classes and all threads in different classes will wait for the lock?

Class StaticClass
{
 Public static IList<Student> student=new List<Student>();
} 


Class ClassA
{
 //add an item in the collection
} 

Class ClassB 
{
 //delete an item in the collection
} 

Class ClassC
{
//lock the collection here 

        lock (StaticClass.student)
        {

          foreach (ConnectionManager con in ConnectionManager.GetAllStudents())
          {
            con.Send(offlinePresence);
          }
        }

}

When I have locked the collection in ClassC, will other threads for classA and ClassB wait? Until the for loop execute nobody is allowed to add or delete items in the collection, because the collection has been locked?

Henk van Boeijen
  • 7,357
  • 6
  • 32
  • 42
bilal
  • 648
  • 8
  • 26
  • Consider [ConcurrentBag Class](https://msdn.microsoft.com/en-us/library/dd381779(v=vs.110).aspx) – Fabio Mar 10 '17 at 13:25
  • 2
    basically yes, but it's better practice to have a separate `static readonly object` just for locking instead of using the list (or make the list `readonly`) so that the referenced object cannot be changed while locked – slawekwin Mar 10 '17 at 13:26
  • For loop you can create a copy(new instance) of list, then adding, removing classes will not affect during your loop. `foreach(var student in students.ToList())...` – Fabio Mar 10 '17 at 13:28
  • You must use the `lock` **EVERYWHERE**... **EVERY TIME** you access the collection **IN ANY WAY** you must lock it. `StaticClass.student.Count`? `lock`! `StaticClass.student[0]`? `lock`! – xanatos Mar 10 '17 at 13:30
  • 1
    See http://stackoverflow.com/questions/251391/why-is-lockthis-bad for more info on @slawekwin's comment. – ProgrammingLlama Mar 10 '17 at 14:42
  • You should never lock on any object except an object whose *only* purpose is to be in a lock. Don't lock on the object you are trying to restrict access to. – Eric Lippert Mar 10 '17 at 18:17

2 Answers2

0

Take a look at System.Collections.Generic.SynchronizedCollection<T> from the System.ServiceModel.dll assembly. All of the locking stuff is built in.

As Fabio said, ConcurrentBag also works, but a separate list context is created for each thread accessing it. When you try and remove items, it works like a queue. Once you've run out of items in your own thread's list, it will then "steal" items from other threads' lists (in a thread-safe way).

For your task, I'm guessing the SynchronizedCollection would be better.

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
0

When your code acquires a lock on an object, it does not block access to that object from other threads. The only thing that happens to this object is that other threads cannot acquire a lock to the same object as long as the lock is not released.

It is common practice to reserve a separate plain object as the target of a lock.

In your example other threads can still access the List<Student> object as long as code does not explicitly lock it first.

Locking can cause serious performance issues (threads waiting for eachother) and in many cases does not need to be implemented explicitly. Just take a look at the Concurrent collection classes of the .NET Framework.

Henk van Boeijen
  • 7,357
  • 6
  • 32
  • 42