Asynchronous Operations

An asynchronous operation is the basic unit of composition in the Asio asynchronous model. Asynchronous operations represent work that is launched and performed in the background, while the user’s code that initiated the work can continue with other things.

Property of synchronous operations

Equivalent property of asynchronous operations

When a synchronous operation is generic (i.e. a template) the return type is deterministically derived from the function and its arguments.

When an asynchronous operation is generic, the completion handler's arguments' types and order are deterministically derived from the initiating function and its arguments.

If a synchronous operation requires a temporary resource (such as memory, a file descriptor, or a thread), this resource is released before returning from the function.

If an asynchronous operation requires a temporary resource (such as memory, a file descriptor, or a thread), this resource is released before calling the completion handler.

The latter is an important property of asynchronous operations, in that it allows a completion handler to initiate further asynchronous operations without overlapping resource usage.

  • 对于同步操作,申请的临时资源在函数返回前释放;
  • 对于异步操作,申请的临时资源在回调函数调用前释放。

Some concepts

In computer science, an algorithm is called non-blocking if failure or suspension of any thread cannot cause failure or suspension of another thread;

Wait-freedom is the strongest non-blocking guarantee of progress, combining guaranteed system-wide throughput with starvation-freedom. An algorithm is wait-free if every operation has a bound on the number of steps the algorithm will take before the operation completes.

Lock-freedom allows individual threads to starve but guarantees system-wide throughput. An algorithm is lock-free if, when the program threads are run for a sufficiently long time, at least one of the threads makes progress (for some sensible definition of progress). All wait-free algorithms are lock-free.

Block就是线程放弃CPU时间片,触发系统调度。当一个线程尝试拿mutex而未果,它就会block,等待下次被调度,继续尝试拿这个mutex.

锁的作用就是让本来可以并发执行的code,按次序执行。另外,编译器出于优化目的会将一些指令重排,有一些方法(memory barrier)可以告诉编译器不要重排。原子操作就是在指令级别上无法打断的操作,中断只能发生在指令与指令之间,所以,单条指令是原子的。当然,在多核处理器上,未必成立。

原子操作是不可分割的,即保证其他线程在操作完成一半时永远不会看到该操作。

值得注意的是,重排不仅发生在编译器,CPU也会处于效率目的对指令进行重排。因此,如果保证代码按照所写的顺序执行是一个很复杂的问题。

CPU 重新排序比编译器重新排序更微妙。 你永远无法直接看到它发生,你只能看到莫名其妙的 bug。 为了防止对读取和写入进行 CPU 重新排序,需要在某些处理器上使用内存屏障指令。

参考链接:https://learn.microsoft.com/zh-cn/windows/win32/dxtecharts/lockless-programming?redirectedfrom=MSDN