C++代码中的死锁

Deadlock in C++ code

本文关键字:死锁 代码 C++      更新时间:2023-10-16

我试图处理代码中的死锁,但我不知道如何防止它。我有一个访问数据的线程和一个更新数据的更新方法。代码如下:

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;
}

写入期间重新启动读取方法的标准方法是使用seqlock。对于单个写入程序读取器,seqlock只是原子整数变量,每次写入程序启动和结束时都会递增。这样reader方法可以定期检查变量是否在read启动后保持不变:

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.
     }
}

如果几个updater()可以同时执行,那么整个update代码应该使用互斥执行:

updater() // *writer*
{
    QMutexLocker locker(&updater_Mutex);
    seq = seq + 1;
    <update data>
    seq = seq + 1;
}

如果即使是单个数据元素也不能在更新的同时访问,那么<update data><process data[i]>都应该使用互斥执行。