I have the following scenario:
I'm trying to lock a thread in place, if that threads 'custom' id matches the one that has already entered the locked section off code, but not if the id differs.
I created some sample code to explain the behaviour I want
class A
{
private static Dictionary<int, object> _idLocks = new Dictionary<int, object>();
private static readonly object _DictionaryLock = new object();
private int _id;
private void A (int id)
{
_id = id;
}
private object getObject()
{
lock (_DictionaryLock)
{
if (!_idLocks.ContainsKey(_id))
_idLocks.Add(_id, new object());
}
lock (_idLocks[_id])
{
if (TestObject.Exists(_id))
return TestObject(_id);
else
return CreateTestObject(_id);
}
}
}
Now this works 100% for what I extended, where id example 1 does not check to see if its object has been created while another thread with id 1 is already busy creating that object.
But having two locks and a static dictionary does not seem correct way of doing it at all, so I'm hoping someone can show me an improved method of stopping a thread from accessing code only if that thread was created with the same id as the one already busy executing the code in the locked section.
I was looking at the ReaderWriterLockSlim class but to me it didn't really make sense to be used cause I don't want object TestObject(id) to be read at all while it's still being created.
I don't care about locking the thread from accessing a dictionary.
What I'm trying to avoid at all cost is the _id which that thread runs should not be used inside CreateTestObject(_id) while there is already one busy, because files are being created and deleted with that id which will throw exceptions if two threads are trying to access the same files
Which is fixable with just a normal lock, but in this case I still want a thread whose _id is not currently running inside the CreateTestObject(_id) method to be able to enter the code within the lock.
This is all because what happens inside CreateTestObject takes time and performance will be impacted if a thread is waiting to access it.
It looks like you're using this code to populate a dictionary in a thread-safe manner - could you use a ConcurrentDictionary instead?
class A {
private static ConcurrentDictionary<int, object> _dictionary = new ConcurrentDictionary<int, object>();
private int _id;
private object GetObject() {
object output = null;
if(_dictionary.TryGetValue(_id, output)) {
return output;
} else {
return _dictionary.GetOrAdd(_id, CreateTestObject(_id));
}
}
}
Edit: If you want to completely eliminate the possibility of invoking duplicate CreateTestObject methods then you can store a wrapper in _dictionary that lazily sets object
class Wrapper {
private volatile object _obj = null;
public object GetObj() {
while(_obj == null) {
// spin, or sleep, or whatever
}
return _obj;
}
public void SetObj(object obj) {
_obj = obj;
}
}
class A {
private static ConcurrentDictionary<int, Wrapper> _dictionary = new ConcurrentDictionary<int, Wrapper>();
private int _id;
private object GetObject() {
Wrapper wrapper = null;
if(_dictionary.TryGetValue(_id, wrapper)) {
return wrapper.GetObj();
} else {
Wrapper newWrapper = new Wrapper();
wrapper = _dictionary.GetOrAdd(_id, newWrapper);
if(wrapper == newWrapper) {
wrapper.SetObj(CreateTestObject(_id));
}
return wrapper.GetObj();
}
}
}
Only one thread will be able to put a new Wrapper in _dictionary at the specified _id - that thread will initialize the object inside of the wrapper == newWrapper conditional. Wrapper#GetObj spins until the object is set, this can be rewritten to block instead.
This can't work, because Monitor (which is used internally by the lock statement) is re-entrant. That means that a thread can enter any lock it already owns any number of times.
You could solve this by using a Semaphore instead of a Monitor, but stop for a while and listen to what you're asking - you want the thread to block on a lock owned by that same thread. How is that thread ever going to wake up? It will deadlock forever - waiting for the lock to be released, while also being the one holding the lock.
Or are you just trying to handle lazy initialization of some object without having to block all the other threads? That's actually quite simple:
ConcurrentDictionary<int, YourObject> dictionary;
return dictionary.GetOrAdd(id, i => CreateTestObject(i));
Note that CreateTextObject is called only if the key doesn't exist in the dictionary yet.
Related
If you've done something like
Thread logSend = new Thread(() => senddat.SendLoggedData());
logSend.Priority = ThreadPriority.AboveNormal;
logSend.Name = "BackLogThread";
logSend.IsBackground = false;
logSend.Start();
Are you able to simply verify at a later point, from another thread, that there IS a thread with the name "BackLogThread" currently running?
I don't want to do anything to the thread, I just want to query the threads inside my application to see if there is one with that particular name.
Edit:
As far as the other question that was asked related to this one, that solution is viable, but it is a little much for what I am asking. The person in that example wants to know a lot about the thread like their priority etc. for logging information. I want at most a true to return if there's any thread anywhere with the name "BackLogThread" running.
As far as I know this is not possible because there's no way to get all managed threads in C#. But you can manually add them to a pool and retrieve them later.
The pool/registry can look like this:
public class ThreadRegistry
{
private static ThreadRegistry instance;
private readonly object syncRoot = new object();
private readonly IDictionary<string, Thread> threads = new Dictionary<string, Thread>();
private ThreadRegistry()
{
}
public static ThreadRegistry Instance => instance ?? (instance = new ThreadRegistry());
public Thread this[string name]
{
get
{
lock (this.syncRoot)
{
return this.threads[name];
}
}
}
public void Register(Thread thread)
{
lock (this.syncRoot)
{
this.threads.Add(thread.Name, thread);
}
}
public bool ThreadExists(string name)
{
lock(this.syncRoot)
{
return this.threads.ContainsKey(name);
}
}
}
Image this code:
You have 2 arrays, and you need to lock both of them in same moment (for any reason - you just need to keep locked both of them because they are somehow depending on each other) - you could nest the lock
lock (array1)
{
lock (array2)
{
... do your code
}
}
but this may result in a deadlock in case that someone in other part of your code would do
lock (array2)
{
lock (array1)
{
... do your code
}
}
and array 1 was locked - execution context switched - then array 2 was locked by second thread.
Is there a way to atomically lock them? such as
lock_array(array1, array2)
{
....
}
I know I could just create some extra "lock object" and lock that instead of both arrays everywhere in my code, but that just doesn't seem correct to me...
In general you should avoid locking on publicly accessible members (the arrays in your case). You'd rather have a private static object you'd lock on.
You should never allow locking on publicly accessible variable as Darin said. For example
public class Foo
{
public object Locker = new object();
}
public class Bar
{
public void DoStuff()
{
var foo = new Foo();
lock(foo.Locker)
{
// doing something here
}
}
}
rather do something like this.
public class Foo
{
private List<int> toBeProtected = new List<int>();
private object locker = new object();
public void Add(int value)
{
lock(locker)
{
toBeProtected.Add(value);
}
}
}
The reason for this is if you have multiple threads accessing multiple public synchronization constructs then run the very real possiblity of deadlock. Then you have to be very careful about how you code. If you are making your library available to others can you be sure that you can grab the lock? Perhaps someone using your library has also grabbed the lock and between the two of you have worked your way into a deadlock scenario. This is the reason Microsoft recommend not using SyncRoot.
I am not sure what you mean by lock to arrays.
You can easily perform operation on both arrays in single lock.
static readonly object a = new object();
lock(a){
//Perform operation on both arrays
}
I need to make a critical section in an area on the basis of a finite set of strings. I want the lock to be shared for the same string instance, (somewhat similar to String.Intern approach).
I am considering the following implementation:
public class Foo
{
private readonly string _s;
private static readonly HashSet<string> _locks = new HashSet<string>();
public Foo(string s)
{
_s = s;
_locks.Add(s);
}
public void LockMethod()
{
lock(_locks.Single(l => l == _s))
{
...
}
}
}
Are there any problems with this approach? Is it OK to lock on a string object in this way, and are there any thread safety issues in using the HashSet<string>?
Is it better to, for example, create a Dictionary<string, object> that creates a new lock object for each string instance?
Final Implementation
Based on the suggestions I went with the following implementation:
public class Foo
{
private readonly string _s;
private static readonly ConcurrentDictionary<string, object> _locks = new ConcurrentDictionary<string, object>();
public Foo(string s)
{
_s = s;
}
public void LockMethod()
{
lock(_locks.GetOrAdd(_s, _ => new object()))
{
...
}
}
}
Locking on strings is discouraged, the main reason is that (because of string-interning) some other code could lock on the same string instance without you knowing this. Creating a potential for deadlock situations.
Now this is probably a far fetched scenario in most concrete situations. It's more a general rule for libraries.
But on the other hand, what is the perceived benefit of strings?
So, point for point:
Are there any problems with this approach?
Yes, but mostly theoretical.
Is it OK to lock on a string object in this way, and are there any thread safety issues in using the HashSet?
The HashSet<> is not involved in the thread-safety as long as the threads only read concurrently.
Is it better to, for example, create a Dictionary that creates a new lock object for each string instance?
Yes. Just to be on the safe side. In a large system the main aim for avoiding deadlock is to keep the lock-objects as local and private as possible. Only a limited amount of code should be able to access them.
I'd say it's a really bad idea, personally. That isn't what strings are for.
(Personally I dislike the fact that every object has a monitor in the first place, but that's a slightly different concern.)
If you want an object which represents a lock which can be shared between different instances, why not create a specific type for that? You can given the lock a name easily enough for diagnostic purposes, but locking is really not the purpose of a string. Something like this:
public sealed class Lock
{
private readonly string name;
public string Name { get { return name; } }
public Lock(string name)
{
if (name == null)
{
throw new ArgumentNullException("name");
}
this.name = name;
}
}
Given the way that strings are sometimes interned and sometimes not (in a way which can occasionally be difficult to discern by simple inspection), you could easily end up with accidentally shared locks where you didn't intend them.
Locking on strings can be problematic, because interned strings are essentially global.
Interned strings are per process, so they are even shared among different AppDomains. Same goes for type objects (so don't lock on typeof(x)) either.
I had a similar issue not long ago where I was looking for a good way to lock a section of code based on a string value. Here's what we have in place at the moment, that solves the problem of interned strings and has the granularity we want.
The main idea is to maintain a static ConcurrentDictionary of sync objects with a string key. When a thread enters the method, it immediately establishes a lock and attempts to add the sync object to the concurrent dictionary. If we can add to the concurrent dictionary, it means that no other threads have a lock based on our string key and we can continue our work. Otherwise, we'll use the sync object from the concurrent dictionary to establish a second lock, which will wait for the running thread to finish processing. When the second lock is released, we can attempt to add the current thread's sync object to the dictionary again.
One word of caution: the threads aren't queued- so if multiple threads with the same string key are competing simultaneously for a lock, there are no guarantees about the order in which they will be processed.
Feel free to critique if you think I've overlooked something.
public class Foo
{
private static ConcurrentDictionary<string, object> _lockDictionary = new ConcurrentDictionary<string, object>();
public void DoSomethingThreadCriticalByString(string lockString)
{
object thisThreadSyncObject = new object();
lock (thisThreadSyncObject)
{
try
{
for (; ; )
{
object runningThreadSyncObject = _lockDictionary.GetOrAdd(lockString, thisThreadSyncObject);
if (runningThreadSyncObject == thisThreadSyncObject)
break;
lock (runningThreadSyncObject)
{
// Wait for the currently processing thread to finish and try inserting into the dictionary again.
}
}
// Do your work here.
}
finally
{
// Remove the key from the lock dictionary
object dummy;
_lockDictionary.TryRemove(lockString, out dummy);
}
}
}
}
I have a simple question about lock.
Are Process1 and Process2 the same because they are eventually locking the LongProcess?
Thank you.
private static readonly object _Locker = new object();
public void Process1()
{
lock(_LockerA){
LongProcess()
}
}
public void Process2()
{
if(curType == A)
ProcessTypeA();
else if(curtype == B)
ProcessTypeB();
}
private static readonly object _LockerA = new object();
public void ProcessTypeA()
{
lock(_LockerA){
LongProcess()
}
}
private static readonly object _LockerB = new object();
public void ProcessTypeB()
{
lock(_LockerB){
LongProcess()
}
}
public void LongProcess()
{
}
No, they are not the same. If you lock against a different object than an already existing lock, then both code paths will be allowed. So, in the case of Process2 curtype == 'b' the lock is using the _LockerB object. If one of the other locks using the _LockerA object is attempted, then they will be allowed to enter the LongProcess.
Process1 and Process2 have the potential to lock the same object, but they are definitely not the same. Locks on the same object are however allowed (I think, rarely if ever had to do it) within the same call stack (also referred to as recursive locking in the case where Process1 invokes Process2). This could likely be better described as dependent locking.
Your question is however fairly vague so you'll have to elaborate on what you mean by the same...
Okay, I just can't get my head around multi-threading scenarios properly. Sorry for asking a similar question again, I'm just seeing many different "facts" around the internet.
public static class MyClass {
private static List<string> _myList = new List<string>;
private static bool _record;
public static void StartRecording()
{
_myList.Clear();
_record = true;
}
public static IEnumerable<string> StopRecording()
{
_record = false;
// Return a Read-Only copy of the list data
var result = new List<string>(_myList).AsReadOnly();
_myList.Clear();
return result;
}
public static void DoSomething()
{
if(_record) _myList.Add("Test");
// More, but unrelated actions
}
}
The idea is that if Recording is activated, calls to DoSomething() get recorded in an internal List, and returned when StopRecording() is called.
My specification is this:
StartRecording is not considered Thread-Safe. The user should call this while no other Thread is calling DoSomething(). But if it somehow could be, that would be great.
StopRecording is also not officially thread-safe. Again, it would be great if it could be, but that is not a requirement.
DoSomething has to be thread-safe
The usual way seems to be:
public static void DoSomething()
{
object _lock = new object();
lock(_lock){
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
Alternatively, declaring a static variable:
private static object _lock;
public static void DoSomething()
{
lock(_lock){
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
However, this answer says that this does not prevent other code from accessing it.
So I wonder
How would I properly lock a list?
Should I create the lock object in my function or as a static class variable?
Can I wrap the functionality of Start and StopRecording in a lock-block as well?
StopRecording() does two things: Set a boolean variable to false (to prevent DoSomething() from adding more stuff) and then copying the list to return a copy of the data to the caller). I assume that _record = false; is atomic and will be in effect immediately? So normally I wouldn't have to worry about Multi-Threading here at all, unless some other Thread calls StartRecording() again?
At the end of the day, I am looking for a way to express "Okay, this list is mine now, all other threads have to wait until I am done with it".
I will lock on the _myList itself here since it is private, but using a separate variable is more common. To improve on a few points:
public static class MyClass
{
private static List<string> _myList = new List<string>;
private static bool _record;
public static void StartRecording()
{
lock(_myList) // lock on the list
{
_myList.Clear();
_record = true;
}
}
public static IEnumerable<string> StopRecording()
{
lock(_myList)
{
_record = false;
// Return a Read-Only copy of the list data
var result = new List<string>(_myList).AsReadOnly();
_myList.Clear();
return result;
}
}
public static void DoSomething()
{
lock(_myList)
{
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
}
Note that this code uses lock(_myList) to synchronize access to both _myList and _record. And you need to sync all actions on those two.
And to agree with the other answers here, lock(_myList) does nothing to _myList, it just uses _myList as a token (presumably as key in a HashSet). All methods must play fair by asking permission using the same token. A method on another thread can still use _myList without locking first, but with unpredictable results.
We can use any token so we often create one specially:
private static object _listLock = new object();
And then use lock(_listLock) instead of lock(_myList) everywhere.
This technique would have been advisable if myList had been public, and it would have been absolutely necessary if you had re-created myList instead of calling Clear().
Creating a new lock in DoSomething() would certainly be wrong - it would be pointless, as each call to DoSomething() would use a different lock. You should use the second form, but with an initializer:
private static object _lock = new object();
It's true that locking doesn't stop anything else from accessing your list, but unless you're exposing the list directly, that doesn't matter: nothing else will be accessing the list anyway.
Yes, you can wrap Start/StopRecording in locks in the same way.
Yes, setting a Boolean variable is atomic, but that doesn't make it thread-safe. If you only access the variable within the same lock, you're fine in terms of both atomicity and volatility though. Otherwise you might see "stale" values - e.g. you set the value to true in one thread, and another thread could use a cached value when reading it.
There are a few ways to lock the list. You can lock on _myList directly providing _myList is never changed to reference a new list.
lock (_myList)
{
// do something with the list...
}
You can create a locking object specifically for this purpose.
private static object _syncLock = new object();
lock (_syncLock)
{
// do something with the list...
}
If the static collection implements the System.Collections.ICollection interface (List(T) does), you can also synchronize using the SyncRoot property.
lock (((ICollection)_myList).SyncRoot)
{
// do something with the list...
}
The main point to understand is that you want one and only one object to use as your locking sentinal, which is why creating the locking sentinal inside the DoSomething() function won't work. As Jon said, each thread that calls DoSomething() will get its own object, so the lock on that object will succeed every time and grant immediate access to the list. By making the locking object static (via the list itself, a dedicated locking object, or the ICollection.SyncRoot property), it becomes shared across all threads and can effectively serialize access to your list.
The first way is wrong, as each caller will lock on a different object.
You could just lock on the list.
lock(_myList)
{
_myList.Add(...)
}
You may be misinterpreting the this answer, what is actually being stated is that they lock statement is not actually locking the object in question from being modified, rather it is preventing any other code using that object as a locking source from executing.
What this really means is that when you use the same instance as the locking object the code inside the lock block should not get executed.
In essence you are not really attempting to "lock" your list, you are attempting to have a common instance that can be used as a reference point for when you want to modify your list, when this is in use or "locked" you want to prevent other code from executing that would potentially modify the list.