與原代碼的問題是,這種複製Foo
對象:
std::thread *t = new std::thread(*obj);
這意味着,增量發生在副本,所以在原來Foo
值不會改變,而因此當main
將其打印出來(如果移動錯位join()
),該值始終相同。
一個解決方案是使用一個參考而不是一個拷貝:
std::thread *t = new std::thread(std::ref(*obj));
您還需要保護變量的互斥鎖的讀取(或使用std::atomic<int>
的計數器),以避免因同時未定義行爲讀寫一個非原子變量。
您也應該直接停止使用mut.lock()
和mut.unlock()
,而不是使用use a scoped lock。
也沒有必要不必要地在堆上創建事物,過度使用new
是先學習Java和C#的人的壞習慣。
您還可以通過用標準C++替換特定於Windows的Sleep
調用來使代碼具有可移植性。
正確的版本是:
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
std::mutex mut;
class Foo
{
public:
Foo(std::chrono::milliseconds m) : m_delay(m), m_count(0)
{}
void update()
{
int count = 0;
{
std::lock_guard<std::mutex> lock(mut);
count = m_count;
}
std::cout << "count: " << count << std::endl;
}
void operator()()
{
while (true)
{
{
std::lock_guard<std::mutex> lock(mut);
m_count++;
}
std::this_thread::sleep_for(m_delay);
}
}
private:
std::chrono::milliseconds m_delay;
int m_count;
};
Foo obj(std::chrono::milliseconds(200));
int main()
{
std::thread t(std::ref(obj));
while(true)
{
obj.update();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
t.join();
return 0;
}
另外,使用原子變量,因此你不需要互斥:
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
class Foo
{
public:
Foo(std::chrono::milliseconds m) : m_delay(m), m_count(0)
{}
void update()
{
std::cout << "count: " << m_count << std::endl;
}
void operator()()
{
while (true)
{
m_count++;
std::this_thread::sleep_for(m_delay);
}
}
private:
std::chrono::milliseconds m_delay;
std::atomic<int> m_count;
};
Foo obj(std::chrono::milliseconds(200));
int main()
{
std::thread t(std::ref(obj));
while(true)
{
obj.update();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
t.join();
return 0;
}
是您的問題:「爲什麼沒有任何被打印出來?」或者這篇文章是更多的聲明? :) –
不需要在這個代碼中使用用戶鎖.... – Netwave
@CroCo你什麼時候期待't-> join()'返回? – Biffen