From the discussion I've seen it seems that atomic operation and thread safety are the same thing, but a lot of people say that they're different. Can anyone tell me the difference if there is one?
Atomic operations are a way to achive thread safety either by using some kind of locks like Mutexes or Semaphores which use atomic operations internally or by implementing lock free synchronization using atomics and memory fences.
So atomic operations on primitive data types are a tool to achive thread safety but do not ensure thread safety automatically because you normally have multiple operations that rely on each other. You have to ensure that these operations are done without interruption eg using Mutexes.
Yes, writing one of these atomic data types in c# is thread safe, but that does not make the function you use them in thread safe. It only ensures that the single write is correctly executed even if a second thread accesses it "at the same time". Never the less, the next read from the current thread is not ensured to get the value previously written as a different thread might have written to it, only that the value read is valid.
Atomicity and thread-safety are two different things. Atomicity refers to an operation's "all-or-nothing" quality; if an operation cannot be performed 100% successfully, then the system should remain in the overall state it had been in before any part of the operation began. The classic example is a database transaction; When saving an invoice, including its header and multiple line items, every single part of every single database row must be put in place successfully; if not, data is lost or corrupted. If a line item cannot be inserted, then not only should no other rows remaining be inserted, but none of the rows already processed should remain.
Thread-safety refers to a combination of things, including atomicity, that allows an operation to be "reentrant"; multiple workers can be performing the same operation, starting at the same or different times, without effect on any other. There are many models for thread-safe operation; most of them boil down conceptually to either running multiple parallel tasks in complete isolation (two workers can perform the same task on two different objects or collections of objects without ever knowing the other worker even exists), or setting up a "pipeline" within which multiple workers each perform one task out of an entire operation (either each worker progresses from the first task to the next and so on, or else focuses on one task and hands off its intermediate "work product" to the next worker).
An atomic operation is an operation that cannot be interrupted.
A safe thread is a thread that can safely be interrupted.
Thread safety is obtained with atomic operations, in particular in the logic that prevents critical resources from being accessed multiple times.
The basic atomic operation is Test-and-set, which is used for implementing semaphores, which in turn are used to implement thread safety.
Thread-safety is more a framework or a "concept", atomic operation is a subset, a means (one of many) of achieving status as being classed 'thread-safe'.
Thread safety refers to a process that can be accessed by separate threads, where the access of one (and manipulation of data), wont corrupt the integrity of the operation of the other.
Much of the skill of the programmer is knowing how to achieve this, depending on the situation and key objective, you may need to implement, for example: locks, semaphores, latches, atomic objects, synchronization rules etc...