Does @Synchronized Guarantees for Thread Safety or Not

atomic properties vs thread safety


In other words, the writing and reading of the atomic property itself is, in fact, “thread safe” (protected from corruption by multiple writers) but of course that protection doesn't extend to any broader logic.

  1. Is this an accurate understanding?

Largely yes.

I would shy away from using the term “thread safe” in that context, though, especially in the context of objects, because the notion that a pointer is not corrupted is a far cry from any practical sense of thread safety of the object itself, much less the broader application logic.


  1. Under what broad circumstances is an atomic property actually useful? I could contrive some simple examples where a property is some sort of counter or changing object that doesn't need to reflect current state, etc, but those seem uncommon versus multithreading scenarios where you really do need explicit locking around the access-- in which case you could have just used nonatomic on the actual property all along.

They can be useful when dealing with primitive data types in specific scenarios (e.g., a boolean state property designating whether some background process is done). They also can be useful in special cases where you are dealing with immutable, stateless objects.

But in most multithreaded scenarios, atomic properties generally fail to achieve thread safety.


  1. Why exactly do people consistently say that atomicity doesn't “guarantee thread safety”? That seems only true in the same way that an NSLock doesn’t guarantee thread safety or synchronized doesn't guarantee thread safety-- a warning for the uninitiated? Otherwise it seems a confusing designation since the very point of these synchronization mechanisms is that they are for use in thread safe design and they are known to be reliable in their designed operation.

We do this because there were people (e.g. https://stackoverflow.com/a/17571453/1271826) who incorrectly suggest that atomic properties achieve thread-safety when it almost always fails to do so. Back in the day, it seemed like whenever someone asked a question about thread safety, someone would chime in with “oh, use atomic properties”. There seemed to be a perennial conflation of “thread safety” and the modest protection against corruption that atomic offers.

So, yes, “has nothing to do with thread safety” is a bit strong. But in the vast majority of cases, atomic properties fail to achieve thread safety, and in the presence of properly implemented synchronization (such as locks, @synchronized, GCD, etc.), just introduce unnecessary overhead.

This is very different than the other synchronization mechanisms (such as locks, etc.). With proper implementation of these mechanisms, one invariably can achieve thread safety. But in many cases (most cases?) atomic simply won’t do the job. Sure, atomic can mitigate one very narrow type of corruption of values/pointers, but that generally doesn’t make one’s code thread safe.

Volatile and Synchronized

Yes, they will get updated version. synchronized guarantees two things: visibility of changes and atomicity. volatile just guarantees visibility of changes. Java guarantees that code inside synchronized block will not be optimized (by mixing commands inside and outside the synchronized block) so every change on variables inside it, will be visible to all threads after the end of synchronized block.

What does @synchronized() do as a singleton method in objective C?

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.

What does 'synchronized' mean?

The synchronized keyword is all about different threads reading and writing to the same variables, objects and resources. This is not a trivial topic in Java, but here is a quote from Sun:

synchronized methods enable a simple
strategy for preventing thread
interference and memory consistency
errors: if an object is visible to
more than one thread, all reads or
writes to that object's variables are
done through synchronized methods.

In a very, very small nutshell: When you have two threads that are reading and writing to the same 'resource', say a variable named foo, you need to ensure that these threads access the variable in an atomic way. Without the synchronized keyword, your thread 1 may not see the change thread 2 made to foo, or worse, it may only be half changed. This would not be what you logically expect.

Again, this is a non-trivial topic in Java. To learn more, explore topics here on SO and the Interwebs about:

  • Concurrency
  • Java Memory Model

Keep exploring these topics until the name "Brian Goetz" becomes permanently associated with the term "concurrency" in your brain.

Is it safe to call a synchronized method from another synchronized method?

Yes, when you mark methods as synchronized, then you are really doing this:

void method1() {
synchronized (this) {
method2()
}
}

void method2() {
synchronized (this) {
}
}

When the thread call gets into method2 from method1, then it will ensure that it holds the lock to this, which it will already, and then it can pass through.

When the thread gets directly into method1 or method2, then it will block until it can get the lock (this), and then it will enter.

As noted by James Black in the comments, you do have to be aware with what you do inside of the method body.

private final List<T> data = new ArrayList<T>();

public synchronized void method1() {
for (T item : data) {
// ..
}
}

public void method3() {
data.clear();
}

Suddenly it's not thread safe because you are looking at a ConcurrentModificationException in your future because method3 is unsynchronized, and thus could be called by Thread A while Thread B is working in method1.

Atomic properties vs thread-safe in Objective-C

An atomic property in Objective C guarantees that you will never see partial writes.
When a @property has the attribute atomic it is impossible to only partially write the value. The setter is like that:

- (void)setProp:(NSString *)newValue {
[_prop lock];
_prop = newValue;
[_prop unlock];
}

So if two threads want to write the value @"test" and @"otherTest" at the same time, then
at any given time the property can only be the initial value of the property or @"test" or @"otherTest".
nonatomic is faster but the value is a garbage value and no partial String of @"test"/@"otherTest" (thx @Gavin) or any other garbage value.

But atomic is only thread-safe with simple use.
It is not garantueed.
Appledoc says the following:

Consider an XYZPerson object in which both a person’s first and last
names are changed using atomic accessors from one thread. If another
thread accesses both names at the same time, the atomic getter methods
will return complete strings (without crashing), but there’s no
guarantee that those values will be the right names relative to each
other. If the first name is accessed before the change, but the last
name is accessed after the change, you’ll end up with an inconsistent,
mismatched pair of names.

I never had a problem using atomic at all. I designed the code that way, that there is not problem with atomic properties.

Code after synchronized block in java


Now, I wondered if the execution will resume from B's nameList.add(name) method while thread A is waiting on 'this' lock object - since nameList.add(name) is not in the sync block.

No, the thread executing the method can't just skip over the block and execute the remaining part of the method. What it will do is block until it can acquire the monitor on this, then execute the synchronized block, then release the monitor on this, then add the string to the nameList.

If concurrent threads execute this, there's no guarantee of which threads will insert into the nameList first. It's possible that between the time that a thread releases the monitor on this and the time that it adds to the nameList one or more other threads might barge in and add to the list.

Also whatever nameList is implemented as needs to be a thread-safe collection, so that concurrent changes don't cause errors and so that changes are visible across threads. If nameList is an ArrayList or a HashSet, for instance, then this would not be safe.



Related Topics



Leave a reply



Submit