MS reference: http://msdn.microsoft.com/en-us/library/3a86s51t(v=vs.71).aspx
"The type of the expression in a SyncLock statement must be a reference type, such as a class, a module, an interface, array or delegate."
Scenario: Multiple threads reading and editing a list.
I know this will avoid a race condition:
SyncLock TheList
TheList.item(0) = "string"
End SyncLock
But will this?
SyncLock TheList.item(0)
TheList.item(0) = "string"
End SyncLock
No, your second snippet is fundamentally wrong. Since you are replacing the object that you lock on. So another thread is going to take the lock on another object, you therefore have no thread-safety at all. A lock can only work if threads use the exact same object to store the lock state.
Notable too is the kind of object you take the lock on. Your second snippet does so on an interned string. Very, very bad since is very likely to cause deadlock. Any other code anywhere else might be wrong the same way and also take a lock on a string literal. If that happens to be "string" as well, you'll easily get completely undiagnosable deadlock.
Also the problem with your first snippet, other code might be taking a lock on the TheList object since it is probably public. Producing deadlock for the same reason. Boilerplate is that you always use a dedicated object to store the lock state that isn't used for anything else, only ever appearing in any code that accesses the list.
Private ListLock As Object = New Object
Related
I realise that I am almost certainly being dense but this is starting to bug me, if you'll pardon the pun.
In my entity datamodel I have a partial class for an entity and within that I have added code to a PropertyChanging event to (I had hoped) assign the value to another of the entity's values based on the call to a stored procedure imported into the model and taking the value of the property in whose propertychanging event it is being used as a parameter.
The basic syntax of the call being made (in vb I should add) is;
Private Sub OnVesselIdChanging(value As Integer)
PortOfLanding = tp.GetDefaultVesselLandingPort(value).SingleOrDefault
End Sub
Used as is it causes a 'NullReferenceException was unhandled by user code'. So to counter this I have tried wrapping it in a try catch block and various other constructs in order to catch null. Obviously I am missing exactly what the null reference is, I know a parameter of the correct value is being passed to the function and I know that there is data in the underlying database to return a value so why is this happening.
I'd like to make proper use of the entity data model so actively understanding the cause of this would be of great help.
Many thanks for your thoughts on the matter.
Option Strict On
Public Class UtilityClass
Private Shared _MyVar As String
Public Shared ReadOnly Property MyVar() As String
Get
If String.IsNullOrEmpty(_MyVar) Then
_MyVar = System.Guid.NewGuid.ToString()
End If
Return _MyVar
End Get
End Property
Public Shared Sub SaveValue(ByVal newValue As String)
_MyVar = newValue
End Sub
End Class
While locking is a good general approach to adding thread safety, in many scenarios involving write-once quasi-immutability, where a field should become immutable as soon as a non-null value is written to it, Threading.Interlocked.CompareExchange may be better. Essentially, that method reads a field and--before anyone else can touch it--writes a new value if and only if the field matches the supplied "compare" value; it returns the value that was read in any case. If two threads simultaneously attempt a CompareExchange, with both threads specifying the field's present value as the "compare" value, one of the operations will update the value and the other will not, and each operation will "know" whether it succeeded.
There are two main usage patterns for CompareExchange. The first is most useful for generating mutable singleton objects, where it's important that everyone see the same instance.
If _thing is Nothing then
Dim NewThing as New Thingie() ' Or construct it somehow
Threading.Interlocked.CompareExchange(_thing, NewThing, Nothing)
End If
This pattern is probably what you're after. Note that if a thread enters the above code between the time another thread has done so and the time it has performed the CompareExchange, both threads may end up creating a new Thingie. If that occurs, whichever thread reaches the CompareExchange first will have its new instance stored in _thing, and the other thread will abandon its instance. In this scenario, the threads don't care whether they win or lose; _thing will have a new instance in it, and all threads will see the same instance there. Note also that because there's no memory barrier before the first read, it is theoretically possible that a thread which has examined the value of _thing sometime in the past might continue seeing it as Nothing until something causes it to update its cache, but if that happens the only consequence will be the creation of a useless new instance of Thingie which will then get discarded when the Interlocked.CompareExchange finds that _thing has already been written.
The other main usage pattern is useful for updating references to immutable objects, or--with slight adaptations--updating certain value types like Integer or Long.
Dim NewThing, WasThing As Thingie
Do
WasThing = _thing
NewThing = WasThing.WithSomeChange();
Loop While Threading.Interlocked.CompareExchange(_thing, NewThing, WasThing) IsNot WasThing
In this scenario, assuming there is some means by which, given a reference to Thingie, one may cheaply produce a new instance that differs in some desired way, it's possible to perform any such operation on _thing in a thread-safe manner. For example, given a String, one may easily produce a new String which has some characters appended. If one wished to append some text to a string in a thread-safe manner (such that if one thread attempts to add Fred and the other tries to add Joe, the net result would be to either append FredJoe or JoeFred, and not something like FrJoeed), the above code would have each thread read _thing, generate a version with its text appended and, try to update _thing. If some other thread updated _thing in the mean-time, abandon the last string that was constructed, make a new string based upon the updated _thing, and try again.
Note that while this approach isn't necessarily faster than the locking approach, it does offer an advantage: if a thread which acquires a lock gets stuck in an endless loop or otherwise waylaid, all threads will be forever blocked from accessing the locked resource. By contrast, if the WithSomeChanges() method above gets stuck in an endless loop, other users of _thing won't be affected.
With multithreaded code, the relevant question is: Can state be modified from several threads? If so, the code isn’t thread safe.
In your code, that’s the case: there are several places which mutate _MyVar and the code is therefore not thread safe. The best way to make code thread safe is almost always to make it immutable: immutable state is simply thread safe by default. Furthermore, code that doesn’t modify state across threads is simpler and usually more efficient than mutating multi-threaded code.
Unfortunately, it’s impossible to see without context whether (or how) your code could be made immutable from several threads. So we need to resort to locks which is slow, error-prone (see the other answer for how easy it is to get it wrong) and gives a false sense of security.
The following is my attempt to make the code correct with using locks. It should work (but keep in mind the false sense of security):
Public Class UtilityClass
Private Shared _MyVar As String
Private Shared ReadOnly _LockObj As New Object()
Public Shared ReadOnly Property MyVar() As String
Get
SyncLock _LockObj
If String.IsNullOrEmpty(_MyVar) Then
_MyVar = System.Guid.NewGuid.ToString()
End If
Return _MyVar
End SyncLock
End Get
End Property
Public Shared Sub SaveValue(ByVal newValue As String)
SyncLock _lockObj
_MyVar = newValue
End SyncLock
End Sub
End Class
A few comments:
We cannot lock on _MyVar since we change the reference of _MyVar, thus losing our lock. We need a separate dedicated locking object.
We need to lock each access to the variable, or at the very least every mutating access. Otherwise all the locking is for naught since it can be undone by changing the variable in another place.
Theoretically we do not need to lock if we only read the value – however, that would require double-checked locking which introduces the opportunity for more errors, so I’ve not done it here.
Although we don’t necessarily need to lock read accesses (see previous two points), we might still have to introduce a memory barrier somewhere to prevent reordering of read-write access to this property. I do not know when this becomes relevant because the rules are quite complex, and this is another reason I dislike locks.
All in all, it’s much easier to change the code design so that no more than one thread at a time has write access to any given variable, and to restrict all necessary communication between threads to well-defined communication channels via synchronised data structures.
If I got
Dim myRect As Rectangle = New Rectangle(0,0,100,100)
Is it necessary or just fine to later do this:
myRect = Nothing
Or it isn't necessary? Thank you.
IF it is necessary, are there other cases it isn't for my variables?
In general, as Joel said, it's unnecessary.
In your specific example, though, it is actually pointless. Rectangle is a value type, so setting it to Nothing is not even affecting an object's reference count; it's assigning a new value (the default value for Rectangle) to your myRect variable. This is analogous to having an Integer variable and setting it to 0 at the end of a method. Doesn't buy you anything.
I should point out that the claim "Setting any variable to Nothing [or null in C#] never accomplishes anything"* is a myth. It is entirely possible that you may have a field in a class which you might as well set to null if the object referenced is no longer needed but you still have a reference to the class instance itself.
As a simplistic example, suppose you had some container class which wraps a T[] array, and you give this container an Empty method. It might make sense to set the container's internal array to null in this method, which would result in zero references to the array object, qualifying it for garbage collection. (You would then create a new array when external code next tried to add a T to the collection.) If you did not set the field to null on Empty, then there would still be a reference to the array (i.e., the field), and so that would be a small amount of memory being used that you really don't need.
Like I said, that's a simplistic example. And honestly, it's rare that you ever need to consider scenarios like that. I just thought I would mention it so that you don't get the wrong impression that setting a field to Nothing literally never accomplishes anything.
*I'm not actually quoting anyone specific here; this is just an over-generalization I've heard stated more than once.
Don't do it. This was important to do in the vb6 days, but for .Net it's possible (though very unlikely) for it to actually throw the garbage collector off and have other unexpected side effects.
I'm confusing myself reading Microsoft's documentation on the Lazy<T>(bool) constructor.
The parameter is described as:
isThreadSafe: true to make this instance usable concurrently by multiple threads; false to make the instance usable by only one thread at a time.
If the code I would normally write in an accessor is:
If _rulesCache Is Nothing Then
SyncLock (_lockRulesCache)
If _rulesCache Is Nothing Then
_rulesCache = New RulesCache()
End If
End SyncLock
End If
Return _rulesCache
Do I want to use True or False in the constructor of the Lazy type?
Private _rulesCache As New Lazy(Of RulesCache)(**?**)
So my accessor becomes:
Return _rulesCache.Value
1) Once the object is created, it can handle multiple thread access internally.
2) I just need to make sure that if there are multiple threads hitting the accessor close to simultaneously and the object doesn't exist, that it only gets created once.
According to the documentation, statement 1 implies that the parameter should be false. Statement 2 implies that the parameter should be true.
I feel like I'm over-thinking this and it's just making me more confused. Or are the two statements above actually at odds with each other, and I should just stick with the manual locking to manage the object instantiation?
Statement 2 is the desired interpretation. The parameter does not affect any behavior of the object after the lazy initialization is complete; it only prevents two threads from accidentally racing and instantiating it twice. You can verify that in Reflector if you're curious.
I've searched StackOverflow and there are many ConcurrentModificationException questions. After reading them, I'm still confused. I'm getting a lot of these exceptions. I'm using a "Registry" setup to keep track of Objects:
public class Registry {
public static ArrayList<Messages> messages = new ArrayList<Messages>();
public static ArrayList<Effect> effects = new ArrayList<Effect>();
public static ArrayList<Projectile> proj = new ArrayList<Projectile>();
/** Clears all arrays */
public static void recycle(){
messages.clear();
effects.clear();
proj.clear();
}
}
I'm adding and removing objects to these lists by accessing the ArrayLists like this: Registry.effects.add(obj) and Registry.effects.remove(obj)
I managed to get around some errors by using a retry loop:
//somewhere in my game..
boolean retry = true;
while (retry){
try {
removeEffectsWithSource("CHARGE");
retry = false;
}
catch (ConcurrentModificationException c){}
}
private void removeEffectsWithSource(String src) throws ConcurrentModificationException {
ListIterator<Effect> it = Registry.effects.listIterator();
while ( it.hasNext() ){
Effect f = it.next();
if ( f.Source.equals(src) ) {
f.unapplyEffects();
Registry.effects.remove(f);
}
}
}
But in other cases this is not practical. I keep getting ConcurrentModificationExceptions in my drawProjectiles() method, even though it doesn't modify anything. I suppose the culprit is if I touched the screen, which creates a new Projectile object and adds it to Registry.proj while the draw method is still iterating.
I can't very well do a retry loop with the draw method, or it will re-draw some of the objects. So now I'm forced to find a new solution.. Is there a more stable way of accomplishing what I'm doing?
Oh and part 2 of my question: Many people suggest using ListIterators (as I have been using), but I don't understand.. if I call ListIterator.remove() does it remove that object from the ArrayList it's iterating through, or just remove it from the Iterator itself?
Top line, three recommendations:
Don't do the "wrap an exception in a loop" thing. Exceptions are for exceptional conditions, not control flow. (Effective Java #57 or Exceptions and Control Flow or Example of "using exceptions for control flow")
If you're going to use a Registry object, expose thread-safe behavioral, not accessor methods on that object and contain the concurrency reasoning within that single class. Your life will get better. No exposing collections in public fields. (ew, and why are those fields static?)
To solve the actual concurrency issues, do one of the following:
Use synchronized collections (potential performance hit)
Use concurrent collections (sometimes complicated logic, but probably efficient)
Use snapshots (probably with synchronized or a ReadWriteLock under the covers)
Part 1 of your question
You should use a concurrent data structure for the multi-threaded scenario, or use a synchronizer and make a defensive copy. Probably directly exposing the collections as public fields is wrong: your registry should expose thread-safe behavioral accessors to those collections. For instance, maybe you want a Registry.safeRemoveEffectBySource(String src) method. Keep the threading specifics internal to the registry, which seems to be the "owner" of this aggregate information in your design.
Since you probably don't really need List semantics, I suggest replacing these with ConcurrentHashMaps wrapped into Set using Collections.newSetFromMap().
Your draw() method could either a) use a Registry.getEffectsSnapshot() method that returns a snapshot of the set; or b) use an Iterable<Effect> Registry.getEffects() method that returns a safe iterable version (maybe just backed by the ConcurrentHashMap, which won't throw CME under any circumstances). I think (b) is preferable here, as long as the draw loop doesn't need to modify the collection. This provides a very weak synchronization guarantee between the mutator thread(s) and the draw() thread, but assuming the draw() thread runs often enough, missing an update or something probably isn't a big deal.
Part 2 of your question
As another answer notes, in the single-thread case, you should just make sure you use the Iterator.remove() to remove the item, but again, you should wrap this logic inside the Registry class if at all possible. In some cases, you'll need to lock a collection, iterate over it collecting some aggregate information, and make structural modifications after the iteration completes. You ask if the remove() method just removes it from the Iterator or from the backing collection... see the API contract for Iterator.remove() which tells you it removes the object from the underlying collection. Also see this SO question.
You cannot directly remove an item from a collection while you are still iterating over it, otherwise you will get a ConcurrentModificationException.
The solution is, as you hint, to call the remove method on the Iterator instead. This will remove it from the underlying collection as well, but it will do it in such a way that the Iterator knows what's going on and so doesn't throw an exception when it finds the collection has been modified.