在中断程序内 变量的加加,这种情况是否会出现BUG!

2019-12-27 19:02发布

先说明一下   a=a+1这条程序语句的执行步骤:
javascript:;

我在想这种情况:
如果执行到第一步,将a的值读到寄存器R中

执行完这一条后,来了个中断就是 a=a-1 !
等执行完 a=a-1 ,这时候重点来了!

我的CPU会回到 a=a+1 的第二步!
R寄存器里面是不知道 a 已经被改变了,所以他还是按照原先的值 加1!
然后在写回到 a !
  
这时候就会出现bug了!
这种情况大伙们有考虑过吗?  要怎么避免?
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
84条回答
落叶知秋
1楼-- · 2020-01-04 20:20
 精彩回答 2  元偷偷看……
redroof
2楼-- · 2020-01-05 02:17
落叶知秋 发表于 2016-12-7 13:34
不知道你用的模型是不是这样处理的?

你这样是个正确的无锁队列,不论任何一方被打断都是安全的。
helislayer
3楼-- · 2020-01-05 06:27
redroof 发表于 2016-12-7 21:18
你这样是个正确的无锁队列,不论任何一方被打断都是安全的。

兄台这个大多数是正确的,但是这个话不可以说
这么满。

首先这个假定是只有一个消费者。如果有多个
消费者线程那结果就不对了。

第二,假定这个是只有一个producer,如果有
两个 producer 线程或者有多级中断都有可能
写入,这个代码也就不对,和 LZ 提到的问题
本质一样。

第三,就算只有一个producer 只有一个消费者。
这个代码仍然有可能不对,因为 wr 有可能会溢出。
如果write 一次写太多,wr 是个 8 位的 int, 那么
累计写超过 256 没有去 read 那结果也是不对的。

如果 wr 是 32 位会相对难溢出一点,但是这个情况
也要有考虑。这个是可以在代码里面有体现的。
我就留给有心的程序员来补全了。
redroof
4楼-- · 2020-01-05 09:22
helislayer 发表于 2016-12-8 01:31
兄台这个大多数是正确的,但是这个话不可以说
这么满。


简单的无锁队列只有一个读一个写。我认为这是不需要说的。用的人都知道。还有,计数器不能超过你cpu位数。不然无法原子读写。
中断里写没检查是否满,但问题不大,应该靠设计保证,因为中断又不能阻塞自己。队列满了你只能丢数据了。

redroof
5楼-- · 2020-01-05 10:23
本帖最后由 redroof 于 2016-12-8 09:08 编辑
helislayer 发表于 2016-12-8 01:31
兄台这个大多数是正确的,但是这个话不可以说
这么满。


我贴一个完整的无锁队列来终结讨论吧。
这是真正完整的代码。模板参数buflen是队列缓存的长度,T是队列里装的数据类型。
读的一方使用GetData,写的一方使用PutData。限制:只能有一个读者和一个写者。读者不能写,写者不能读。
为了防止队列空的时候去读或者队列满了去写,读写之前都应该用isFull和Len来检查。这两个函数任何地方都可以用。
不管是用于中断和应用程序或者多个线程之间传递数据,都可以随便用。
你看看还有没有什么问题

template<int buflen, typename T>
        class TLocklessQueue
{
protected:
        T BufData[buflen];
        int PutIdx;
        int GetIdx;

public:
        int MaxSize() {
                return buflen;
        }

        int Len() {
                return (PutIdx - GetIdx + buflen) % buflen;
        }

        bool isFull() {
                return Len() == buflen - 1;
        }

        bool isEmpty() {
                return PutIdx == GetIdx;
        }

        void PutData(const T &aput) {
                int aa = PutIdx + 1;
                aa %= buflen;
                BufData[PutIdx] = aput;
                PutIdx = aa;
        }

        T GetData() {
                int aa = GetIdx + 1;
                aa %= buflen;
                T aget = BufData[GetIdx];
                GetIdx = aa;
                return aget;
        }
};
knight_sh
6楼-- · 2020-01-05 11:28
 精彩回答 2  元偷偷看……

一周热门 更多>