Spin locks available in Windows and Pthread

Source: Internet
Author: User
Tags posix

Spin locks are available in both Windows and POSIX, and we can also implement spin locks with c++11 Atomic. So what is the relationship between the two properties? Introduce the implementation code first:

#ifndef __spinlock_h__#define__spinlock_h__#include<atomic>#ifdef _win32#include<Windows.h>classspinlock_mutex{ Public:    Staticconstexpr DWORD Spinlock_count =-1; Public:    //during initialization, there is a problem with insufficient resources, which is ignored here .//specific reference critical Sections and Error handling (Windows via C + +)Spinlock_mutex () {InitializeCriticalSectionAndSpinCount (&M_cs, Spinlock_count); }    ~Spinlock_mutex () {deletecriticalsection (&M_cs); }    void Lock() {entercriticalsection (&M_cs); }    BOOLTry_lock () {returnTryEnterCriticalSection (&m_cs) = =TRUE; }    voidunlock () {LeaveCriticalSection (&M_cs); }Private: critical_section M_cs;};#elifDefined (_posix_c_source)#include<pthread.h>classspinlock_mutex{ Public:    //there is no handling of possible call errorsSpinlock_mutex () {Pthread_spin_init (&M_cs, pthread_process_private); }    ~Spinlock_mutex () {Pthread_spin_destroy (&M_cs); }    void Lock() {Pthread_spin_lock (&M_cs); }    BOOLTry_lock () {returnPthread_spin_trylock (&m_cs) = =0; }    voidunlock () {Pthread_spin_unlock (&M_cs); }Private: pthread_spinlock_t M_cs;};#elseclassspinlock_mutex{std::atomic_flag Flag; Public: Spinlock_mutex (): flag{atomic_flag_init} {}void Lock()    {         while(Flag.test_and_set (Std::memory_order_acquire)); }    voidunlock () {flag.clear (std::memory_order_release); }    BOOLTry_lock () {return!Flag.test_and_set (Std::memory_order_acquire); }};#endif#endif    //__spinlock_h__

Here is a simple test, two sets of threads, one for inserting and the other for taking out. The test results show:

(1) Both Windows and POSIX-provided C-language spin locks are similar to those used by c++11 to build spin locks using atomic.

(2) with the same number of insert threads and the number of threads removed, the more threads, the less efficient.

Here is the test code:

#include <memory>#include<cassert>#include<iostream>#include<vector>#include<thread>#include<future>#include<random>#include<chrono>#include"spinlock.h"#include<forward_list>structstudent_name{Student_name (intAge =0): Age, Next (nullptr) {}intAge ; Student_name*next;}; Spinlock_mutex g_mtx;std::forward_list<int>g_students;std::atomic<int> g_inserts;//Insert num (successful)std::atomic<int> g_drops;//Drop num (successful)std::atomic<int> g_printnum;//As same as G_dropsstd::atomic<Long Long> g_ageinsum;//Age sum when producing student_namestd::atomic<Long Long> g_ageoutsum;//Age sum when consuming student_namestd::atomic<BOOL> GoOn (true); constexprintInsert_thread_num =1; constexprintDrop_thread_num =1; constexprintOne_thread_produce_num =5000000;//When testing, no more than this number, you know 20,000,00 * * * ~= max_int if thread num <=inlinevoidPrintone (student_name*t) {G_printnum.fetch_add (1, std::memory_order_relaxed); G_ageoutsum.fetch_add (t-Age , std::memory_order_relaxed); G_drops.fetch_add (1, std::memory_order_relaxed); Deletet;}voidInsert_students (intIdno)    {std::d efault_random_engine dre (Time (nullptr)); Std::uniform_int_distribution<int> AgeDi (1, About);  for(inti =0; i < One_thread_produce_num; ++i) {intNewAge =ageDi (DRE);        G_ageinsum.fetch_add (NewAge, std::memory_order_relaxed); {Std::lock_guard<spinlock_mutex>Lock(G_MTX);                    G_students.push_front (NewAge); }        //Use memory_order_relaxed avoiding affect folly memory orderG_inserts.fetch_add (1, std::memory_order_relaxed); }}voidDrop_students (intIdno) {     while(Auto go =goon.load (Std::memory_order_consume)) {{Std::forward_list<int>tmp; {Std::lock_guard<spinlock_mutex>Lock(G_MTX);            Std::swap (g_students, TMP); } Auto It=Tmp.begin ();  while(It! =Tmp.end ()) {G_printnum.fetch_add (1, std::memory_order_relaxed); G_ageoutsum.fetch_add (*it, std::memory_order_relaxed); G_drops.fetch_add (1, std::memory_order_relaxed); ++it; }        }    }}intMain () {Auto start=Std::chrono::system_clock::now (); Std::vector<std::future<void>>insert_threads; Std::vector<std::future<void>>drop_threads;  for(Auto i =0; I! = Insert_thread_num; ++i) {insert_threads.push_back (Std::async (Std::launch::async, insert_students, i)); }     for(Auto i =0; I! = Drop_thread_num; ++i) {drop_threads.push_back (Std::async (Std::launch::async, drop_students, i)); }     for(auto&thread:insert_threads) {Thread.Get(); } std::this_thread::sleep_for (Std::chrono::milliseconds ( +)); Goon.store (false, std::memory_order_release);  for(auto&thread:drop_threads) {Thread.Get(); } {std::forward_list<int>tmp; {Std::lock_guard<spinlock_mutex>Lock(G_MTX);        Std::swap (g_students, TMP); } Auto It=Tmp.begin ();  while(It! =Tmp.end ()) {G_printnum.fetch_add (1, std::memory_order_relaxed); G_ageoutsum.fetch_add (*it, std::memory_order_relaxed); G_drops.fetch_add (1, std::memory_order_relaxed); ++it; }} Auto End=Std::chrono::system_clock::now (); Std::chrono::d uration<Double> diff = end-start; Std::cout<<"Time to insert and drop is:"<< Diff.count () <<"s\n"; Std::cout<<"Insert Count1:"<< g_inserts.load () <<Std::endl; Std::cout<<"Drop Count1:"<< g_drops.load () <<Std::endl; Std::cout<<"Print Num1:"<< g_printnum.load () <<Std::endl; Std::cout<<"Age in1:"<< g_ageinsum.load () <<Std::endl; Std::cout<<"Age OUT1:"<< g_ageoutsum.load () <<Std::endl; Std::cout<<Std::endl;}

For optional locks, the following information is required:

(1) Application layer with Spinlock the biggest problem is not the same as kernel off interrupt (cli/sti), assuming that the concurrency is slightly more points, thread 1 in the lock after the unlock occurred clock interrupt,
* It will not be cut back for a while. Call unlock, then another thread that calls lock in this time does not hollow run while? This is where CPU time is most wasted.
* So can not shut down the interruption can only sleep, how there are huge conflict costs.

(2) Specific reference: https://www.zhihu.com/question/55764216

Spin locks available in Windows and Pthread

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.