Golang synchronization: Atomic operation using

Source: Internet
Author: User
Tags value store

An atomic operation is an operation that cannot be interrupted during the process. Atomic operation for a value in the process of being carried out, the CPU will never go to another operation for that value.
To achieve this rigor, atomic operations are represented and completed only by a separate CPU instruction.

    • The Go language provides atomic operations that are non-invasive, represented by a number of functions in the standard library sync/atomic
    • Types include Int32,int64,uint32,uint64,uintptr,unsafe. Pointer, a total of six.
    • These functions provide a total of five atomic operations: increase or decrease, compare and exchange, load, store and exchange
int various types of value range
type Length (bytes) Value Range
int8 1 -128 ~ 127
Uint8 (Byte) 1 0 ~ 255
Int16 2 32768~32767
UInt16 2 0~65535
Int32 4 2147483648~2147483647
UInt32 4 0~4294967295
Int64 8 -9223372036854775808~9223372036854775807
UInt64 8 0~18446744073709551615
Int Platform-related Platform-related
UInt Platform-related Platform-related
UIntPtr Same pointer 32 bits flat down to 4 bytes, 64 bits flat down to 8 bytes
Increase or decrease add

The function name is prefixed with add and followed by the name of the specific type.

    • The type being manipulated can only be numeric type
    • Int32,int64,uint32,uint64,uintptr types can use atomic increment or decrement operations
    • The first parameter value must be a pointer-type value to impose a special CPU instruction
    • The type of the second parameter value is always the same as the type of the first manipulated value.
Example
 PackageMainImport("FMT"    "Sync/atomic")funcMain () {varI32Int32Fmt. Println ("=====old i32 value=====") FMT. Println (I32)The first parameter value must be a pointer-type value, because the function needs to obtain the position of the manipulated value in memory in order to impose a special CPU instruction    //End returns the new value after atomic operationNEWI32: = Atomic. AddInt32 (&i32, 3) FMT. Println ("=====new i32 value=====") FMT. Println (I32) fmt. Println (NEWI32)varI64Int64Fmt. Println ("=====old i64 value=====") FMT. Println (i64) newI64: = Atomic. AddInt64 (&i64, -3) FMT. Println ("=====new i64 value=====") FMT. Println (i64) fmt. Println (NEWI64)}

Results:
/usr/local/go/bin/go Run/users/liuxinming/go/src/free/learngo/atomic/add/add.go
=====old i32 value=====
0
=====new i32 value=====
-3
-3
=====old i64 value=====
0
=====new i64 value=====
-3
-3

Compare and Exchange CAs

Compare and swaps are referred to as CAs, and in sync/atomic packages, such atomic operations are represented by a number of functions prefixed by the name ' Compareandswap '.

    • Declare as follows
func CompareAndSwapInt32(addr *int32newint32bool)
    • When the function is called, the value of the manipulated value pointed to by the parameter addr is equal to that of the parameter old.
    • The old value is replaced with the new value represented by the parameter new only if the result is positive, otherwise the operation is ignored.
    • So, it needs to be tried continuously with a for loop until it succeeds

    • The practice of using locks tends to be pessimistic

      • We always assume that there will be concurrent operations to modify the value of the operation and to use the lock to secure the relevant operation into the critical section
    • The practice of using CAS tends to be optimistic
      • Always assume that the manipulated value has not been changed (that is, equal to the old value) and that the value is replaced as soon as the authenticity of the hypothesis is confirmed.
Example
 PackageMainImport("FMT"    "Sync/atomic")varValueInt32funcMain () {FMT. Println ("======old value=======") FMT. Println (value) fmt. Println ("======cas value=======") AddValue(3) FMT. Println (Value)}//continually attempt to update the value of values atomically, until the operation succeedsfuncAddValue (DeltaInt32){//The CAS operation is not so easy to succeed in cases where the manipulated values are frequently changed    //so had to use a for loop for multiple attempts     for{V: = valueifAtomic.compareandswapint32 (&value, V, (v + delta)) {//When the result value of the function is true, exit the loop             Break}the reason for the failure of the operation is always that the old value of value is not equal to the value of V.        Although the//cas operation does not allow a goroutine to block on a statement, it may temporarily stop the execution of the abortion, but most of the time is extremely short.}}

Results:
======old value=======
0
======cas value=======
3

Load load

The above comparison and Exchange case total v:= value for variable v assignment, but ... It is important to note that during the operation of reading value, other read and write operations on this value can be performed concurrently, and the read operation is likely to read a data that is only half modified.

    • So, we're going to use the Sync/atomic code package to also provide us with a series of functions that are prefixed with load (load) to ensure that such a bad thing happens.
Example
 PackageMainImport("FMT"    "Sync/atomic")varValueInt32funcMain () {FMT. Println ("======old value=======") FMT. Println (value) fmt. Println ("======cas value=======") AddValue(3) FMT. Println (Value)}//continually attempt to update the value of values atomically, until the operation succeedsfuncAddValue (DeltaInt32){//The CAS operation is not so easy to succeed in cases where the manipulated values are frequently changed    //so had to use a for loop for multiple attempts     for{//v: = value        //In the process of reading value, other read and write operations on this value can be performed concurrently, and the read operation is likely to read a data that is only half modified.        ///So we're going to use loadV: = Atomic. LoadInt32 (&value)ifAtomic.compareandswapint32 (&value, V, (v + delta)) {//When the result value of the function is true, exit the loop             Break}the reason for the failure of the operation is always that the old value of value is not equal to the value of V.        Although the//cas operation does not allow a goroutine to block on a statement, it may temporarily stop the execution of the abortion, but most of the time is extremely short.}}
    • Atomic. LoadInt32 accepts a pointer value of type *int32
    • Returns the value that the pointer points to
Storage Store

The write operation corresponds to the read operation. The Sync/atomic package also provides a stored function of the value of the atom corresponding to the load function of the atom. The store is prefixed with

    • In the process of storing a value atomically, any CPU does not perform a read or write operation on the same value.
    • The atomic value store operation is always successful because it does not care what the old value of the manipulated value is
    • differs significantly from CAS operations
    fmt.Println("======Store value=======")    atomic.StoreInt32(&value, 10)    fmt.Println(value)
Swap swap
    • Unlike CAS operations, atomic Exchange operations do not care about the old values being manipulated.
    • It will set the new value directly
    • It returns the old value of the manipulated value
    • Such operations are less restrictive than CAS operations and are more powerful than atomic loading operations
Actual case (continue to transform the previous version of the code)
//Data file implementation typetypeMydatafilestruct{f *os. File//DocumentsFmutex sync. Rwmutex//read-write lock used for fileRcond *sync. Cond//The condition variable to be used for the read operationWoffsetInt64 //The offset to be used for write operationsRoffsetInt64 //The offset to be used for the read operationDatalenUInt32 //Data block length}//omitted here ...func(DF *mydatafile) Read () (RSNInt64, d Data, err error) {//Read and update read offset    varOffsetInt64     for{offset = atomic. LoadInt64 (&df.roffset)ifAtomic.compareandswapint64 (&df.roffset, offset, offset +Int64(Df.datalen))) { Break}    }//Read a data block, last read block serial numberRSN = offset/Int64(df.datalen) Bytes: = Make([]byte, Df.datalen)//Read/write Lock: Read lockDf.fmutex.RLock ()deferDf.fmutex.RUnlock () for{_, Err = Df.f.readat (bytes, offset)ifErr! =Nil{ifErr = = Io. EOF {//Temporarily discard Fmutex's read lock and wait for notification to arriveDf.rcond.Wait ()Continue}        } Break} d = bytesreturn}func(DF *mydatafile) Write (d Data) (WSNInt64, err Error) {//Read and update the write offset    varOffsetInt64     for{offset = atomic. LoadInt64 (&df.woffset)ifAtomic.compareandswapint64 (&df.woffset, offset, offset +Int64(Df.datalen))) { Break}    }//write a data block and write the serial number of the data block lastWSN = offset/Int64(Df.datalen)varbytes []byte    if Len(d) >int(Df.datalen) {bytes = d[0:d F.datalen]}Else{bytes = d} df.fmutex.Lock ()deferDf.fmutex.Unlock () _, err = Df.f.write (bytes)//Send notificationsDf.rcond.Signal ()return}func(DF *mydatafile) RSN ()Int64{offset: = atomic. LoadInt64 (&df.roffset)returnOffset/Int64(Df.datalen)}func(DF *mydatafile) WSN ()Int64{offset: = atomic. LoadInt64 (&df.woffset)returnOffset/Int64(Df.datalen)}

Complete code on GitHub:
Https://github.com/lxmgo/learngo

Some of the learning process to organize, I hope you learn the go language to help.

Golang synchronization: Atomic operation using

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.