[Multithreading] lock-free programming and CAS

No programming lock / lock-free / non-blocking synchronization

Lock-free programming, that is, when not in use lock variable synchronization between multiple threads, which is synchronized variable in the absence of the thread is blocked, it is also called non-blocking synchronization (Non-blocking Synchronization).
Non-blocking synchronization scheme is called "lock-programming algorithm" (Non-blocking algorithm).
lock-free is the most common implementation of lock-free programming level (a total of three levels).

Why Non-blocking sync?

Use lock thread synchronization realize there are a lot of disadvantages:
* When in competition, the thread is blocked waiting for, can not do real-time response thread.
* dead lock。
* live lock。
* Priority inversion.
* Improper use, resulting in performance degradation.
 
If the lock is not used in the case, to achieve synchronization variable, it will avoid many problems. Although now, lock-free programming and is not a substitute lock.

Implementation level

Achieve asynchronous blocking can be divided into three levels: wait-free / lock-free / obstruction-free.
 
wait-free
Is the best mode, the entire operation is completed to ensure that each thread in limited steps.
System level guaranteed throughput (system-wide throughput) and a wireless starvation process.
As of 2011, little concrete implementation. Even if achieved, but also need to rely on the specific CPU.
 
lock-free
Allow individual thread starvation, but to ensure the system level throughput.
Ensure that at least one thread can continue execution.
wait-free algorithms must also of lock-free.
 
obstruction-free
At any point in time, a thread is isolated execution (Suspended other threads) to a transaction, and is completed within a finite number of steps. During execution, the data is modified if it is found (using a time stamp, a version number), the rollback.
Also known as optimistic locking, that optimistic concurrency control (OOC ) . The transaction process is: 1 to read, write and time stamp; 2 ready to write version check; 3 by check is written, verification is not passed, then rolled back.
lock-free must be the obstruction-free.

CAS primitives

LL/SC, atom read-modify-write
If the CPU provides Load-Link / Store-Conditional (LL / SC) this instruction, you can easily lock variable without CPU level synchronization.
LL [addr], dst: dst to read value from memory [addr] at.
SC value, [addr]: For the current thread, since LL action last memory value has not changed, it is updated with the new values.
The above process is implemented atoms lock-free operation of the read-modify-write.
 
CAS (Compare-And-Swap)
LL / SC This CPU instruction is not achieved, then we need to find other algorithms, such as CAS.
CAS is a primitive set of instructions used to implement variable in a multi-thread synchronization.
X86 CMPXCHG instruction achieved under CAS, either pre-LOCK achieve atomicity operations. As of 2013, most of multi-core processors are supported by CAS.
CAS primitive has three parameters, memory addresses, the expected value, new value. If the value of the memory address == expected value, indicating that the unmodified value, at this time may be modified to a new value. Otherwise it means modification fails, it returns false, decided to follow-up operation by the user.
Copy the code
Bool CAS(T* addr, T expected, T newValue) 
 { 
      if( *addr == expected ) 
     { 
          *addr =  newValue; 
           return true; 
     } 
     else 
           return false; 
 }
Copy the code

 

ABA problem
thread1 intended to operate val = 1 becomes 2, cas (* val, 1,2).
thread1 first read val = 1; thread1 preempted (preempted), so thread2 operation.
thread2 modify val = 3, and back to 1.
thread1 continue, expectations and found "at cost" (in fact, been modified) identical, complete CAS operation.
 
Use CAS ABA causes problems, especially when using a number of concurrent data structure pointer during operation.
 
solution
ABA': Adding additional tags to indicate whether or not modified.

Language

Java demo
AtomicInteger atom = new AtomicInteger(1);
boolean r = atom.compareAndSet(1, 2);
 
C# demo
int i=1;
Interlocked.Increment(ref i);
 
 
Supplementary: ConcurrentLinkedQueue (cycle CAS + wait-free concurrent algorithms volatile implemented)

Guess you like

Origin www.cnblogs.com/itplay/p/11121691.html