关于多线程同步问题(不同对象的同一代码是否也需要同步)

时间:2022-05-16 18:12:23
最近初学Qt,一直以来对多线程等都不是特别熟悉,这几天学Qt遇到了一个疑惑,希望大家指导指导。

学习用书:C++ GUI Qt 4 编程(第二版)
问题:    Page 258,代码如下。就是在使用QMutex进行线程的同步执行时,使用两个按钮分别打印A和B,点击A按钮开始A线程,点击B按钮开始B线程,A线程开始后,按钮就会变成stop,再次点击stop就可以关闭A线程,B也一样,A和B是两个不同的对象。
    我主要的问题是,在 void Thread::stop() 里,不需要对stopped上锁,我的理解是A和B是两个不同的对象,他们的stopped是独立的吧,所以A操作stopped时,B也stopped应该没影响,需要上锁的一般是全局变量什么的吧?
    按照我这样的理解,但是我又测试了一下,在 void Thread::stop() 的stopped下面增加一个sleep(5),然后我都开启了A、B线程,然后又关闭了B,但是在5秒内却关闭不了A,又让我感觉它们处理的是同一个stopped,希望各位给予一个答复,感激不尽。


void Thread::run()
{

    forever{
        mutex.lock();
        if(stopped){
            stopped = false;
            mutex.unlock();
            break;
        }
        mutex.unlock();
        std::cerr << qPrintable(messageStr);
    }

    std::cerr << std::endl;
}

void Thread::stop()
{
    mutex.lock();
    stopped = true;
    mutex.unlock();
}

7 个解决方案

#1


哪些跨线程需要访问的内存地址需要写保护,要看是否跨线程访问了同一个地址,而且还是改变里边的内容。

#2


引用 1 楼 foxyz 的回复:
哪些跨线程需要访问的内存地址需要写保护,要看是否跨线程访问了同一个地址,而且还是改变里边的内容。


那我这个应该访问的不是同一内存地址吧?

#3


因为在 void Thread::stop() 的stopped下面增加一个sleep(5),这时没有mutex.unlock(),stop()不能重入。

可以在 void Thread::stop() 的mutex.unlock();下面增加一个sleep(5),试一试。已经解锁,可以重入。

#4


引用 3 楼 guoliang624 的回复:
因为在 void Thread::stop() 的stopped下面增加一个sleep(5),这时没有mutex.unlock(),stop()不能重入。

可以在 void Thread::stop() 的mutex.unlock();下面增加一个sleep(5),试一试。已经解锁,可以重入。


也就是说虽然是两个对象,但是访问同一代码也需要锁吗?那 void Thread::stop() 在两个对象中地址不是不一样的吗?

#5


引用 4 楼 HuiLom 的回复:
Quote: 引用 3 楼 guoliang624 的回复:

因为在 void Thread::stop() 的stopped下面增加一个sleep(5),这时没有mutex.unlock(),stop()不能重入。

可以在 void Thread::stop() 的mutex.unlock();下面增加一个sleep(5),试一试。已经解锁,可以重入。


也就是说虽然是两个对象,但是访问同一代码也需要锁吗?那 void Thread::stop() 在两个对象中地址不是不一样的吗?

那 void Thread::stop() 在两个对象中地址应该是一样的, 你可以把函数地址打印出来,用函数指针。

#6


这个不需要加锁,前提stopped非静态的

#7


这里根本不需要加锁,你理解的没错,这个不同对象的各自变量根本无关。但有一点,这个锁可不是这么回事,虽然他是属于各自类的成员变量,但是一旦锁住其余的绝对进不去。你不可以想成二个人有一模一样的锁,我锁了不影响其余的。这个东西可不是这样的。

#1


哪些跨线程需要访问的内存地址需要写保护,要看是否跨线程访问了同一个地址,而且还是改变里边的内容。

#2


引用 1 楼 foxyz 的回复:
哪些跨线程需要访问的内存地址需要写保护,要看是否跨线程访问了同一个地址,而且还是改变里边的内容。


那我这个应该访问的不是同一内存地址吧?

#3


因为在 void Thread::stop() 的stopped下面增加一个sleep(5),这时没有mutex.unlock(),stop()不能重入。

可以在 void Thread::stop() 的mutex.unlock();下面增加一个sleep(5),试一试。已经解锁,可以重入。

#4


引用 3 楼 guoliang624 的回复:
因为在 void Thread::stop() 的stopped下面增加一个sleep(5),这时没有mutex.unlock(),stop()不能重入。

可以在 void Thread::stop() 的mutex.unlock();下面增加一个sleep(5),试一试。已经解锁,可以重入。


也就是说虽然是两个对象,但是访问同一代码也需要锁吗?那 void Thread::stop() 在两个对象中地址不是不一样的吗?

#5


引用 4 楼 HuiLom 的回复:
Quote: 引用 3 楼 guoliang624 的回复:

因为在 void Thread::stop() 的stopped下面增加一个sleep(5),这时没有mutex.unlock(),stop()不能重入。

可以在 void Thread::stop() 的mutex.unlock();下面增加一个sleep(5),试一试。已经解锁,可以重入。


也就是说虽然是两个对象,但是访问同一代码也需要锁吗?那 void Thread::stop() 在两个对象中地址不是不一样的吗?

那 void Thread::stop() 在两个对象中地址应该是一样的, 你可以把函数地址打印出来,用函数指针。

#6


这个不需要加锁,前提stopped非静态的

#7


这里根本不需要加锁,你理解的没错,这个不同对象的各自变量根本无关。但有一点,这个锁可不是这么回事,虽然他是属于各自类的成员变量,但是一旦锁住其余的绝对进不去。你不可以想成二个人有一模一样的锁,我锁了不影响其余的。这个东西可不是这样的。