简体   繁体   English

是否可以使用std :: atomic_flag在C ++中获得线程锁定机制?

[英]Is possible to get a thread-locking mechanism in C++ with a std::atomic_flag?

Using MS Visual C++2012 使用MS Visual C ++ 2012

A class has a member of type std::atomic_flag 类具有std::atomic_flag类型的成员

class A {
    public:
    ...
    std::atomic_flag lockFlag;
    A () { std::atomic_flag_clear (&lockFlag); } 
};

There is an object of type A 有一个类型A的对象

A object;

who can be accessed by two (Boost) threads 谁可以被两个(Boost)线程访问

void thr1(A* objPtr) { ... }
void thr2(A* objPtr) { ... }

The idea is wait the thread if the object is being accessed by the other thread. 如果另一个线程正在访问该对象,则该想法是等待该线程。

The question is: do it is possible construct such mechanism with an atomic_flag object? 问题是:是否有可能使用atomic_flag对象构造这样的机制? Not to say that for the moment, I want some lightweight that a boost::mutex. 不是说暂时,我想要一些轻量级的boost :: mutex。

By the way the process involved in one of the threads is very long query to a dBase who get many rows, and I only need suspend it in a certain zone of code where the collision occurs (when processing each row) and I can't wait the entire thread to finish join() . 顺便说一下,其中一个线程涉及的进程是一个非常长的查询到获得很多行的dBase,我只需要在发生冲突的某个代码区域中挂起它(当处理每一行时)我不能等待整个线程完成join()

I've tryed in each thread some as: 我在每个帖子中试过一些:

thr1 (A* objPtr) {
    ...
    while (std::atomic_flag_test_and_set_explicit (&objPtr->lockFlag, std::memory_order_acquire)) {
        boost::this_thread::sleep(boost::posix_time::millisec(100));
    }
    ...  /* Zone to portect */

    std::atomic_flag_clear_explicit (&objPtr->lockFlag, std::memory_order_release);
    ...  /* the process continues  */
}

But with no success, because the second thread hangs. 但没有成功,因为第二个线程挂起。 In fact, I don't completely understand the mechanism involved in the atomic_flag_test_and_set_explicit function. 实际上,我并不完全理解atomic_flag_test_and_set_explicit函数中涉及的机制。 Neither if such function returns inmediately or can delay until the flag can be locked. 如果这样的函数不能立即返回,或者可以延迟直到可以锁定标志。

Also it is a mistery to me how to get a lock mechanism with such a function who always set the value, and return the previous value. 对我来说,如何获得一个具有这样一个函数的锁定机制并始终设置该值并返回之前的值也是一种谜。 with no option to only read the actual setting. 没有选项只能读取实际设置。

Any suggestion are welcome. 欢迎任何建议。

By the way the process involved in one of the threads is very long query to a dBase who get many rows, and I only need suspend it in a certain zone of code where the collision occurs (when processing each row) and I can't wait the entire thread to finish join(). 顺便说一下,其中一个线程涉及的进程是一个非常长的查询到获得很多行的dBase,我只需要在发生冲突的某个代码区域中挂起它(当处理每一行时)我不能等待整个线程完成join()。

Such a zone is known as the critical section . 这样的区域被称为临界区 The simplest way to work with a critical section is to lock by mutual exclusion . 使用关键部分的最简单方法是通过互斥来锁定。

The mutex solution suggested is indeed the way to go, unless you can prove that this is a hotspot and the lock contention is a performance problem. 建议的互斥解决方案确实是要走的路,除非你能证明这是一个热点并且锁争用是一个性能问题。 Lock-free programming using just atomic and intrinsics is enormously complex and cannot be recommended at this level. 仅使用原子和内在函数的无锁编程非常复杂,不能在此级别上推荐。

Here's a simple example showing how you could do this (live on http://liveworkspace.org/code/6af945eda5132a5221db823fa6bde49a ): 这是一个简单的例子,展示了如何做到这一点(生活在http://liveworkspace.org/code/6af945eda5132a5221db823fa6bde49a ):

#include <iostream>
#include <thread>
#include <mutex>

struct A
{
    std::mutex mux;
    int x;

    A() : x(0) {}
};

void threadf(A* data)
{
    for(int i=0; i<10; ++i)
    {
        std::lock_guard<std::mutex> lock(data->mux);
        data->x++;
    }
}

int main(int argc, const char *argv[])
{
    A instance;
    auto t1 = std::thread(threadf, &instance);
    auto t2 = std::thread(threadf, &instance);

    t1.join();
    t2.join();

    std::cout << instance.x << std::endl;

    return 0;
}

It looks like you're trying to write a spinlock. 看起来你正试图写一个自旋锁。 Yes, you can do that with std::atomic_flag , but you are better off using std::mutex instead. 是的,你可以使用std::atomic_flag来做到这std::atomic_flag ,但你最好还是使用std::mutex Don't use atomics unless you really know what you're doing. 除非你真的知道自己在做什么,否则不要使用原子。

To actually answer the question asked: Yes, you can use std::atomic_flag to create a thread locking object called a spinlock. 要实际回答问题:是的,您可以使用std :: atomic_flag创建一个名为spinlock的线程锁定对象。

#include <atomic>

class atomic_lock
{
    public:
        atomic_lock()
            : lock_( ATOMIC_FLAG_INIT )
        {}

        void lock()
        {
            while ( lock_.test_and_set() ) { } // Spin until the lock is acquired.
        }

        void unlock()
        {
            lock_.clear();
        }

    private:
        std::atomic_flag lock_;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM