C ++代码中的死锁

时间:2015-10-30 17:50:47

标签: c++ qt concurrency deadlock

我尝试在代码中处理死锁但我无法理解如何防止它。我有一个访问数据的线程和一个更新数据的更新方法。代码如下所示:

thread {
    forever {
        if (Running) {
            LOCK
                access data
            UNLOCK
        }
         Running = false;
    }
}

update {
    Running = false;

    LOCK
        access data
    UNLOCK

    Running = true;
}

我尝试用第二个访问变量修复它,但它没有改变任何东西。

thread {
    forever {
        if (!Updating) {
            if (Running) {
                LOCK
                     access data
                UNLOCK
            }
        }
         Running = false;
    }
}

update {
    Updating = true;
    Running = false;

    LOCK
        access data
    UNLOCK

    Updating = false;
    Running = true;
}

感谢您的帮助。

更新 这是对问题的更好描述:

thread {
    forever {
        if (Running) {
            LOCK
                if (!Running) leave
                access data
            UNLOCK
        }
        Running = false;
    }
}

update {
    Running = false;

    LOCK
        access data
    UNLOCK

    Running = true;
}

我的更新功能有点复杂,因此我无法看到使用标准算法之一的方法。

更新2 这是简化的c ++源代码。或许最好以伪代码的形式阅读:

void run() {
    forever {
        if (mRunning) {

            QMutexLocker locker(&mMutex);
            for (int i; i < 10; i++) {
                qDebug("run %d", i);
                sleep(1);
                if (!mRunning) break;
            }

            mRunning = false;
        }
    }
}

void update() {
    mRunning = false;

    QMutexLocker locker(&mMutex);

    qDebug("update");

    mRunning = true;
}

更新3 好。问题有点复杂。我忘了我在线程中访问数据部分也启动了一些子线程来填充数据结构

datathread {
    access data
}

thread {
    forever {
        if (Running) {
            LOCK
                if (!Running) leave

                forloop
                    start datathread to fill data to accessdata list
            UNLOCK
        }
        Running = false;
    }
}

update {
    Running = false;

    LOCK
        access data
    UNLOCK

    Running = true;
}

1 个答案:

答案 0 :(得分:0)

Standard way for read method being restarted when during write is to use seqlock. With single writer and reader seqlock is just atomic integer variable, which is incremented every time when writer is started and when it is ended. Such a way reader method can periodically check whether variable is unchanged since read is started: atomic<int> seq = 0; updater() // *writer* { seq = seq + 1; <update data> seq = seq + 1; } thread() // *reader* { retry: // Start point of unmodified data processing. { int seq_old = seq; if(seq_old & 1) { // odd value of the counter means that updater is in progress goto retry; } for(int i = 0; i < 10; i++) { <process data[i]> if(seq_old != seq) { // updater has been started. Restart processing. goto retry; } } // Data processing is done. } } If several updater() can be executed concurrently, whole update code should be executed with mutex taken: updater() // *writer* { QMutexLocker locker(&updater_Mutex); seq = seq + 1; <update data> seq = seq + 1; } If even single element of data cannot be accessed concurrently with updating, both <update data> and <process data[i]> should be executed with mutex taken.