phaser
“phaser”是一個同步原語,它允許線程知道所有其他線程已經通過執行中的某個點,但沒有阻塞任何這些線程。 在調用者想要在解除分配之前保證共享資源不再可見的情況下,它非常有用。
任何數量的線程都可以進入和退出由移相器保護的“關鍵區域”; 他們使用例程退出phaser_enter和phaser_exit。 這些功能是非等待,非阻塞,完全可重入,絕對可靠和異步信號安全。
另一個線程(一次最多一個)可以同時調用phaser_drain。 此函數會阻塞所有線程在調用phaser_drain之前進入受監控區域 相應的調用phaser_exit退出該區域。
phaser_enter和phaser_exit是異步信號安全的并且完全可重入,使得它們非常適用于其他同步原語可能很麻煩的信號處理程序。
性能
Phaser非常重量級。 phaser_enter和phaser_exit是常見情況下的原子增量和原子減量。 在Intel i7-4600U上,phaser_enter和phaser_exit對在大約28個周期內完成。 如果phaser_drain同時運行,那么成本大約會翻倍。
雖然移相器本身可以充分執行,但它只占用一個緩存行,可能會在嚴重爭用的情況下損害性能。 通過使用多個相位器(每個相位器位于不同的高速緩存線上),調用者可以在這種情況下將性能提高兩倍。 進入關鍵部分的線程可以根據CPU親和性選擇移相器,并且想要在所有讀取器上同步的線程可以依次調用每個高速緩存行上的phaser_drain。
可移植性
Phaser依賴于操作系統提供某種等待地址功能。 在Linux上,我們直接使用futex。 在Windows上,可以使用WaitOnAddress。 在FreeBSD上,umtx應該可以工作; 在iOS上,內核的psynch_cvwait psynch_cvsignal就足夠了。
例子
請注意,worker_threads()不執行重量級同步,并且對worker_threads()和atomically_increment_array()的任何數量的調用都可以并發運行。
std::vector<int>* g_array; pthread_mutex_t array_phaser_lock = PTHREAD_MUTEX_INITIALIZER; phaser_t array_phaser;void init() {pthread_mutex_init(&array_phaser_lock);phaser_init(&array_phaser); }void worker_threads() {phaser_phase phase;for(;;) {phase = phaser_enter(array_phaser);operate_on_array(array);phaser_exit(array_phaser, phase);} }void atomically_increment_array() {std::vector<int>* old_array;std::vector<int>* new_array;bool success;do {phaser_enter(array_phaser);old_array = __atomic_load_n(&g_array, __ATOMIC_ACQUIRE);// NB: in real code, the std::vector constructor can throw,// and calling code should take care to exit the phaser// critical section if it does.new_array = new std::vector<int>(*old_array);for(auto it = new_array->begin(); it != new_array->end(); ++it) {*it += 1;}// Important to use __ATOMIC_RELEASE on the success path:// other threads must see only fully-constructed vector.success =__atomic_compare_exchange_n(&g_array,&old_array,new_array,true // weak: we loop anyway,__ATOMIC_RELEASE,__ATOMIC_RELAXED);phaser_exit(array_phaser);if(!success) {* Someone else beat us to the increment, so try again.delete new_array;}} while(!success);// We exclusively own the old array. Wait for pending readers// to finish.pthread_mutex_lock(&array_phaser_lock);phaser_drain(array_phaser);pthread_mutex_unlock(&array_phaser_lock);// Now we know that nobody is using old_array: all// references to array occur inside a phaser critical// section, and the call to phaser_drain ensured that// all critical sections that began while g_array still// pointed at old_array have now terminated.delete old_array; } 復制代碼轉載于:https://juejin.im/post/5ce12d8051882539133cbfea
總結
- 上一篇: centos7安装nvidia驱动
- 下一篇: [转] Vuex入门(2)—— stat