类似这样:
thread readthread(&Teacher164::readfunc,tea);
thread readthread(&Teacher164::readfunc,&tea);
//当我们在构造一个 thread的时候,如下代码对应 readthread,writethread,
//如果第二个参数传递的是 Teacher164对象 tea,那么会有copy 构造函数的调用。
//如果 我们在传递第二个参数的时候, 传递的是Teacher164对象的tea的地址,相当于多个线程中都会共享这个tea,这才会让在 Teacher164类中的list是同一个,才有共享数据的可能性。
class Teacher164 {
public:
//共享数据 存在list中
list msgListQueue;
public:
//读取 共享数据的线程方法
void readfunc() {
int readcount = 0;
while (true && readcount!=100000) {
//只要不为空,就可以读取数据
if (!msgListQueue.empty()) {
int readvalue = msgListQueue.front();//每次都读取第一个
cout << "读取到的值为" << readvalue << endl;
msgListQueue.pop_front();//删除第一个元素
readcount++;
}
else {
cout << "没有读取到值" << endl;
}
}
}
//写入 共享数据的线程方法
void writefunc() {
for (size_t i = 0; i < 100000; i++)
{
msgListQueue.push_back(i);//每次都写到末尾
cout << "写入元素的值为" << i << endl;
}
}
public:
Teacher164() {
cout << "Teacher164 构造方法 this = " << this << endl;
}
Teacher164(const Teacher164 & obj) {
cout << "Teacher164 copy 构造方法 this = " << this << " obj = " << &obj<< endl;
}
~Teacher164() {
cout << "Teacher164 析构函数 this = " << this << endl;
}
};
//当我们在构造一个 thread的时候,如下代码对应 readthread,writethread,
//如果第二个参数传递的是 Teacher164对象 tea,那么会有copy 构造函数的调用。
//如果 我们在传递第二个参数的时候, 传递的是Teacher164对象的tea的地址,相当于多个线程中都会共享这个tea,这才会让在 Teacher164类中的list是同一个,才有共享数据的可能性。
void main() {
Teacher164 tea;
thread readthread(&Teacher164::readfunc,tea);
thread writethread(&Teacher164::writefunc, tea);
readthread.join();
writethread.join();
//如上,调用的时候,tea是值传递的时候,会调用 copy 构造函数
//Teacher164 构造方法 this = 00000092A277F508
// Teacher164 copy 构造方法 this = 000002713BA6C420 obj = 00000092A277F508
// Teacher164 copy 构造方法 this = 000002713BA75310 obj = 00000092A277F508
// Teacher164 析构函数 this = 000002713BA6C420
// Teacher164 析构函数 this = 000002713BA75310
// Teacher164 析构函数 this = 00000092A277F508
cout << "=========================" << endl;
}
//传递 是地址: thread readthread1(&Teacher164::readfunc, &tea1);
结果是:只要使用的 &tea1 的线程,都使用的同一个tea(地址是一样的,没有copy 构造函数调用),这就有可能让其共享数据
void main(){
Teacher164 tea1;
thread readthread1(&Teacher164::readfunc, &tea1);
thread writethread1(&Teacher164::writefunc, &tea1);
//thread 的构造方法第二个参数 可以是地址,如果是地址,那么 readthread1 和 writethread1的传递就是同一个 teacher
// Teacher164 构造方法 this = 000000265F4FFB68
// Teacher164 析构函数 this = 000000265F4FFB68
}
//我们先把问题简化,假设有2个线程,一个线程 读数据,一个线程写数据。但是运行确一直没有问题。
//于是搞4个线程,2个读数据,2个写数据
class Teacher164 {
public:
//共享数据 存在list中
list msgListQueue;
public:
//读取 共享数据的线程方法
void readfunc() {
int readcount = 0;
while (true && readcount!=100000) {
//只要不为空,就可以读取数据
if (!msgListQueue.empty()) {
int readvalue = msgListQueue.front();//每次都读取第一个
cout << "读取到的值为" << readvalue << endl;
msgListQueue.pop_front();//删除第一个元素
readcount++;
}
else {
cout << "没有读取到值" << endl;
}
}
}
//写入 共享数据的线程方法
void writefunc() {
for (size_t i = 0; i < 100000; i++)
{
msgListQueue.push_back(i);//每次都写到末尾
cout << "写入元素的值为" << i << endl;
}
}
public:
Teacher164() {
cout << "Teacher164 构造方法 this = " << this << endl;
}
Teacher164(const Teacher164 & obj) {
cout << "Teacher164 copy 构造方法 this = " << this << " obj = " << &obj<< endl;
}
~Teacher164() {
cout << "Teacher164 析构函数 this = " << this << endl;
}
};
void main() {
cout << "=========================" << endl;
Teacher164 tea1;
thread readthread1(&Teacher164::readfunc, &tea1);
thread writethread1(&Teacher164::writefunc, &tea1);
//thread 的构造方法第二个参数 可以是地址,如果是地址,那么 readthread1 和 writethread1的传递就是同一个 teacher
thread readthread2(&Teacher164::readfunc, &tea1);
thread writethread2(&Teacher164::writefunc, &tea1);
readthread1.join();
readthread2.join();
writethread1.join();
writethread2.join();
}
由于要保护共享数据,我们的思路是:在操作时可以将共享数据锁住,其他想操作共享数据的线程必须等待解锁。
是std中的一个类。
std::mutex。。。在标头
class mutex; (C++11 起)
多个线程尝试用mutex 的 成员函数 lock() 来加锁 这把锁头,只有一个线程能锁定成功。(成功的标志是lock函数返回)。
没有锁定成功的线程会卡在这里,并不断地尝试的锁这把锁头。
锁定成功的线程将数据处理完成后,需要调用unlock()释放锁头。
由于释放了锁头,那么如果还有线程 尝试锁这把锁头,就会去抢。
mutex使用时要小心,lock()后,就应该要unlock().。要注意的是,如果是if等判断语句,一个进口,多个出口的情况,在进口的时候lock了,那么在每一个出口都要注意unlock。
mutex中间保护的数据要合适,主要是保护 共享数据。
如果共享数据没有保护全,则还是会发生混乱;
如果除了共享数据,还保护了其他一些不必要的数据,则会影响效率
使用:
mutex mymutex;
mutex mymutex2;
class Teacher165 {
public:
//共享数据 存在list中
list msgListQueue;
mutex mymutex;
int readcount = 0;//记录已经读取了多少个。
public:
//读取 共享数据的线程方法
void readfunc() {
while (true ) {
//只要不为空,就可以读取数据
if (readcount>=200) {
break;
}
mymutex.lock();
if (!msgListQueue.empty()) {
int readvalue = msgListQueue.front();//每次都读取第一个
cout << "读取到的值为" << readvalue << " readcount = " << readcount <