What does #synchronized() do as a singleton method in objective C? - objective-c

I just created a singleton method, and I would like to know what the function #synchronized() does, as I use it frequently, but do not know the meaning.

It declares a critical section around the code block. In multithreaded code, #synchronized guarantees that only one thread can be executing that code in the block at any given time.
If you aren't aware of what it does, then your application probably isn't multithreaded, and you probably don't need to use it (especially if the singleton itself isn't thread-safe).
Edit: Adding some more information that wasn't in the original answer from 2011.
The #synchronized directive prevents multiple threads from entering any region of code that is protected by a #synchronized directive referring to the same object. The object passed to the #synchronized directive is the object that is used as the "lock." Two threads can be in the same protected region of code if a different object is used as the lock, and you can also guard two completely different regions of code using the same object as the lock.
Also, if you happen to pass nil as the lock object, no lock will be taken at all.

From the Apple documentation here and here:
The #synchronized directive is a
convenient way to create mutex locks
on the fly in Objective-C code. The
#synchronized directive does what any
other mutex lock would do—it prevents
different threads from acquiring the
same lock at the same time.
The documentation provides a wealth of information on this subject. It's worth taking the time to read through it, especially given that you've been using it without knowing what it's doing.

The #synchronized directive is a convenient way to create mutex locks on the fly in Objective-C code.
The #synchronized directive does what any other mutex lock would do—it prevents different threads from acquiring the same lock at the same time.
Syntax:
#synchronized(key)
{
// thread-safe code
}
Example:
-(void)AppendExisting:(NSString*)val
{
#synchronized (oldValue) {
[oldValue stringByAppendingFormat:#"-%#",val];
}
}
Now the above code is perfectly thread safe..Now Multiple threads can change the value.
The above is just an obscure example...

#synchronized block automatically handles locking and unlocking for you. #synchronize
you have an implicit lock associated with the object you are using to synchronize. Here is very informative discussion on this topic please follow How does #synchronized lock/unlock in Objective-C?

Excellent answer here:
Help understanding class method returning singleton
with further explanation of the process of creating a singleton.

#synchronized is thread safe mechanism. Piece of code written inside this function becomes the part of critical section, to which only one thread can execute at a time.
#synchronize applies the lock implicitly whereas NSLock applies it explicitly.
It only assures the thread safety, not guarantees that. What I mean is you hire an expert driver for you car, still it doesn't guarantees car wont meet an accident. However probability remains the slightest.

Related

Concurrency in kotlin also block after synchronized block

I have a block of code like this in kotlin.
synchronized(this) {
// do some work and produces a String
}.also { /*it: String*/
logger.log(it)
}
can some thread come and with unlucky timing the it variable gets changed before logging happens? (There are a lot of threads executing this piece of code concurrently)
To expand on comments:
The synchronized block returns a reference that's passed into the also block as it; that reference is local to the thread, and so there's no possibility of it being affected by other threads.
In general, there's no guarantee about the object that that reference points to: if other threads have a reference to it, they could potentially change its state (or that of other objects it refers to).But in this case, it's a String; and in Kotlin, Strings are completely immutable. So there's no risk of that here.
Taking those together: the logging in OP's code is indeed thread-safe!
However:
We can't tell whether there could be race conditions or other concurrency issues within the synchronized block, before the String gets created and returned. It synchronizes on this, which prevents two threads simultaneously executing it on the same object; but if there are two instances of the class, each one could have a single thread running it.So for example there could be an issue if the block uses some common object that's not completely thread-safe, or some instance property that's set to the same reference in both instances, or if there's sharing in a more roundabout way. Obviously, this will depend upon the nature of the work done in that block, what objects it accesses, and what it does with them. So that's worth bearing in mind too.

Does #synchronize protect Objects that are pointed to by other Objects?

For example let's say we have objectA, which points to ObjectB, which points to objectC.
We then do
#synchronized(objectA) {
[self doSomeStuff];
}
What is protected here from other threads? Just objectA, or objectB and objectC and anything that any object references all the way down?
#synchronized(obj) {...} merely means that whatever is in the {...} will not be executed concurrently with any other #synchronized(obj)'s {...}.
I.e. given:
thread 1:
#synchronized(objectA) {
[self doSomeStuff];
}
thread 2:
#synchronized(objectA) {
[self doSomeStuff];
}
thread 3:
[self doSomeStuff];
One of thread 1 or thread 2 will block while the other executes doSomeStuff, but thread 3 will merrily invoke doSomeStuff concurrently.
And, more directly to your question, that implies that, no, there is absolutely zero concurrency protection for anything that doSomeStuff might do internally.
If you want your objects to be "thread safe", they need to be designed from top to bottom with concurrency in mind (and that does not generally mean with tons of locks or synchronization primitives everywhere).
#synchronized(objectA) creates critical section. In your example it guarantees, that [self doSomeStuff] will not be executed simultaneously by different threads.
objectA is used just to identify which implicitly created recursive lock will be used. Critical sections, created by #synchronized directive with same object as argument will not be executed simultaneously.
From Apple documentation:
The #synchronized directive is a convenient way to create mutex locks
on the fly in Objective-C code. The #synchronized directive does what
any other mutex lock would do—it prevents different threads from
acquiring the same lock at the same time. In this case, however, you
do not have to create the mutex or lock object directly. Instead, you
simply use any Objective-C object as a lock token
The object passed to the #synchronized directive is a unique
identifier used to distinguish the protected block. If you execute the
preceding method in two different threads, passing a different object
for the anObj parameter on each thread, each would take its lock and
continue processing without being blocked by the other. If you pass
the same object in both cases, however, one of the threads would
acquire the lock first and the other would block until the first
thread completed the critical section.

How to end a polling thread created with detachNewThreadSelector?

I'm creating a new thread using detachNewThreadSelector ref with toTarget self.
The purpose of the thread is to poll movements and load images as appropriate - it loops and only quits when an atomic bool is set to true in the main thread - which is set in the objects dealloc.
The problem is caused by this (from the detachNewThreadSelector reference):
The objects aTarget and anArgument are retained during the execution of the detached thread, then released
Which means my object will always have a (minimum) retain count of one - because the thread continuously polls. dealloc is therefore never called.
So my question is: how can I dealloc my object taking into account the existence of the polling thread?
The only idea I have right now is to create a destroyThread function of the object, which sets the end thread bool, which would be called from everywhere I'd expect the object to be destroyed. This seems error-prone, are there better solutions?
Thanks in advance.
Update
I had an idea for another solution - in the thread I detect if the retain count is one - if it's one then I know the thread is keeping the object alive, so I break the loop and dealloc is called. Is this a robust solution?
First, avoid detachNewThreadSelector:. Anything you are thinking of doing with it is almost certainly done better with a dispatch queue or NSOperationQueue. Even if you need to manually create a thread (which is exceedingly rare in modern ObjC), it is better to create explicit NSThread objects and hold onto them rather than using detachNewThreadSelector: which creates a thread you can't interact directly with anymore.
To the specific question, if you create your own threads, then you'll need to set that bool somewhere other than dealloc. That means that some other part of the program needs to tell you to shut down. You can't just be released and automatically clean yourself up using manual threads this way.
EDIT: Never, ever call retainCount. No solution involving retainCount is a good solution. Putting aside the various practical problems with using retainCount in more general cases, in this case it ties you manual reference counting. You should switch to ARC as quickly as possible, and retainCount is illegal in ARC (it should have been illegal before ARC, but they finally had a really good excuse to force the issue). If you can't implement your solution in ARC, it is unlikely a good solution.
Again, the best solution is to use GCD dispatch queues (or operations, which are generally implemented with dispatch queues). It is incredibly more efficient and effective for almost every problem than manual thread management.
If you must use a manual thread for legacy code and need to maintain this kind of auto-destruct, the solution is a helper object that owns the thread. Your object owns the helper object, which has a retain loop with the thread. When your object is deallocated, then it tells the thread to shut down, which breaks the retain loop, and the helper object goes away. This is a standard way of managing retain loops.
See Apple's Migrating Away From Threads for more.

Using #synchronized(self) { ... } in class-function

Accidentally I have been using a #synchronized block with the semaphore self in a class method.
+(void)someFunction {
#synchronized(self) {
/* some code */
}
}
It seems to be valid code, at least the compiler does not give me any bad feedback. My question is: what is self here? As far as I can tell the #synchronized block didn't work, but it didn't crash either.
I'm just asking out of curiousity.
self in this instance refers to the class, instead of an instance. In ObjC, classes are themselves objects.
self in this context is the class itself, it's perfectly fine to use #synchronized in a class function since they are also Objective-C objects.
The #synchronized syntax is a compiler extension for mutex implementation. I assume you understood what it does. The compiler will translate it into something else, supposedly something similar to critical section because it's less CPU intensive. Locks need to be tracked. The implementation will use an object to record the state of the lock, to keep its integrity (i.e. a lock shouldn't be acquired twice, or unlocked twice).
In #synchronized(self), the object doesn't have to be self. It could be any objective-c object. Note that a single #synchronized block usually does nothing (when you mentioned it's not working, it's actually behaving correctly). But when you have two #synchronized blocks on the same object, only one block will be executed at the same time, the other block would have to wait for the lock to be unlocked (i.e. the first block finishes). This helps to keep things synchronized as in a multithreaded environment.
In a class method self is the class that the method is being called on. For example you can call other class methods of the same class using self. [MyClass someFunction] and [self someFunction] would be the equivalent to recursively calling someFunction. The #synchronized block I am sure worked as it was supposed to.

Changing the locking object inside #synchronized section

Can I do any of the following? Will they properly lock/unlock the same object? Why or why not? Assume there are many identical threads using global variable "obj", which was initialized before all threads started.
1.
#synchronized(obj) {
[obj release];
obj = nil;
}
2.
#synchronized(obj) {
obj = [[NSObject new] autorelease];
}
Short answer: no, they won't properly lock/unlock, and such approaches should be avoided.
My first question is why you'd want to do something like this, since these approaches nullify the purposes and benefits of using a #synchronized block in the first place.
In your second example, once a thread changes the value of obj, every subsequent thread that reaches the #synchronized block will synchronize on the new object, not the original object. For N threads, you'd be explicitly creating N autoreleased objects, and the runtime may create up to N recursive locks associated with those objects. Swapping out the object on which you synchronize within the critical section is a fundamental no-no of thread-safe concurrency. Don't do it. Ever. If multiple threads can safely access a block concurrently, just omit the #synchronized entirely.
In your first example, the results may be undefined, and certainly not what you want, either. If the runtime only uses the object pointer to find the associated lock, the code may run fine, but synchronizing on nil has no perceptible effect in my simple tests, so again you're using #synchronized in a pointless way, since it offers no protection whatsoever.
I'm honestly not trying to be harsh, since I figure you're probably just curious about the construct. I'm just wording this strongly to (hopefully) prevent you and others from writing code that is fatally flawed, especially if under the assumption that it synchronizes properly. Good luck!