Memory recovery hazard Pointer in parallel programming

Source: Internet
Author: User

After the use of RCU technology to realize the read-write thread unlocked, in the absence of a GC mechanism in the language, to implement the lock free algorithm, it is unavoidable to deal with the memory recovery problem.

Hazard pointer is another algorithm to deal with this problem, and it is not only simple but also powerful. The lock-independent data structure and Hazard pointers are very good, Wikipedia Hazard pointer is also described more clearly, so I'm not so thin here.

A simple implementation can refer to my GitHub haz_ptr.c

Principle

The basic principle is that a read thread identifies a pointer, and the pointer (the memory pointed to) is cached when it is released and deferred until it is confirmed that there is no read thread to actually release it.

<Lock-Free Data Structures with Hazard Pointers>In the description:

Each reader thread owns a single-writer/multi-reader shared pointer called "Hazard pointer." When a reader thread assigns the address of a maps to its hazard pointer, it's basically announcing to other threads (writ ERS), "I am reading this map. You can replace it with it if you want, but Don's change its contents and certainly keep your deleteing hands off it. "

Key structures include: Hazard pointer ,Thread Free list

Hazard pointer: When a read thread is to use a pointer, a hazard pointer is created to wrap the pointer. A hazard pointer will be written by one thread and read by multiple threads.

struct Hazardpointer {        void *real_ptr;//wrapper pointer ...//        different implementations have different members    };    void Func () {        Hazardpointer *hp = Accquire (_real_ptr);        ...//Use _real_ptr        release (HP);    }

Thread Free List: Each thread has a list that holds the list of pointers that will be freed, and this list is read-only by the corresponding thread

void Defer_free (void *ptr) {        _free_list.push_back (PTR);    }

When a thread tries to release a pointer in the free list, such as a pointer ptr , it checks the hazard pointer used by all other threads, checks for the existence of a wrapped ptr hazard pointer, and if not, indicates that no read thread is in use ptrand can be safely released ptr .

void GC () {for        (ptr in _free_list) {            conflict = False for            (HP in _all_hazard_pointers) {                if (Hp->_real_ ptr = = ptr) {                    confilict = True break                }            }            if (!conflict)                delete ptr        }    }

Above, in fact is Hazard Pointer the main content.

Management of Hazard pointer

The above code does not mention _all_hazard_pointers accquire the specific implementation, this is hazard pointer management issues.

The lock free data structure and hazard pointers create a linked list of lock free to represent this global hazard Pointer List. Each hazard pointer has a member that identifies whether it is available. The list also preserves the collection of hazard pointer that have been used and the unused hazard pointer collection, and when all hazard pointer are used, a new one is added to the list. When a read thread does not use a pointer, it needs to return the hazard Pointer and set the available member identifiers directly. If you want gc() , simply traverse the list.

It is very simple to implement a linked list of lock free and only need to implement a header insertion. itself hazard pointer identifies a pointer, it is used immediately after identification, so this implementation directly supports the dynamic thread, support thread hangs and so on.

In the NBDs project there is also a hazard pointer implementation, relatively weaker. It sets its own hazard pointer pool for each thread, and when the write thread wants to release the pointer, it accesses the hazard pointer pool for all other threads.

typedef struct HAZ_LOCAL {        //free List        pending_t *pending,//To be freed        int pending_size;        int pending_count;        Hazard Pointer Pond, dynamic and static two kinds of        haz_t static_haz[static_haz_per_thread];        haz_t **dynamic;        int dynamic_size;        int dynamic_count;    } __ATTRIBUTE__ ((Aligned (cache_line_size))) haz_local_t;    Static haz_local_t Haz_local_[max_num_threads] = {};

Each thread, of course haz_local_ , involves the allocation of an index (ID), just like using RCU technology to implement a read-write thread without a lock. This implementation, in order to support thread dynamic creation, requires a set of thread ID reuse mechanisms, relatively more complex.

Appendix

Finally, some concepts in parallel programming are attached.

Lock Free & Wait Free

Often seen Lock Free and Wait Free concepts, these concepts are used to measure the parallel level of a system or a piece of code, and the parallel level can refer to parallel programming-the concurrency level. Anyway, wait free is a much better level than lock free.

My own understanding, such as the "lock-independent data structure and hazard pointer" Implementation of the hazard pointer linked list can be said to be lock free, note that it is inserted into the new element to the list header, because CAS the use of a busy loop is always unavoidable, In the case of this feature, the Lock Free execution of a thread is affected by other threads, although it is not locked.

In contrast, the Wait Free execution of each thread is independent, such as the function in the lock-independent data structure and hazard pointers Scan .“每个线程的执行时间都不依赖于其它任何线程的行为”

Lock-Independent (lock-free) means that there is always a thread in the system that can continue to execute, while waiting for nothing (Wait-free) is a stronger condition, which means that all threads can go down.

ABA Issues

In the implementation Lock Free of the algorithm, always use CAS the original language, and CAS will bring ABA problems.

In the case of CAS operations, because the CAS primarily asked "V's value is still a" before changing V, the CAS-based algorithm would be confusing if the value was changed from a to B and then to a after the first read of V, and before the CAS operation was performed on V. In this scenario, the CAS operation succeeds. This kind of problem is called ABA problem.

Wiki Hazard Pointer mentioned a good example of an ABA problem: in a lock free stack implementation, now to the stack, the stack of elements is [A, B, C] , point to the head top of the stack, then there is compare_and_swap(target=&head, newvalue=B, expected=A) . But in this operation, the other threads A B are all out of the stack, deleted B , and A pressed into the stack, that is [A, C] . Then the previous thread compare_and_swap succeeds, head pointing to an already deleted one B . StackOverflow also has an example Real-world examples for ABA in multithreading

The usual solution for this ABA problem from CAS is to use a variant of CAs DCAs. DCAS, which is a token for each V to add a reference to the number of modifications. For each V, if the reference is modified once, the counter is incremented by 1. Then, when the variable needs to be update, it checks both the value of the variable and the value of the counter.

But it was also early DCAS to suggest that it was not an ABA problem silver bullet.

Original address: http://codemacro.com/2015/05/03/hazard-pointer/
Written by Kevin Lynx posted athttp://codemacro.com

Memory recovery hazard Pointer in parallel programming

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.