例如:
struct A {
void run1() {}
void run2() {}
};
int main()
{
A a;
thread t1(bind(&A::run1, ref(a)));
thread t2(bind(&A::run2, ref(a)));
// not joinable thread!
int i;
std::cin >> i;
}
请查看此示例http://developer.gnome.org/glibmm/unstable/thread_2thread_8cc-example.html
a 对象是否应受互斥锁或其他内容的保护?这里没有竞争条件吗?
答案 0 :(得分:3)
这取决于方法中的代码。如果方法中没有比赛则没问题。由于没有代码,因此在您的示例中没有;)
在您的示例中,“a”可能会在线程退出之前被销毁(如果用户速度很快)。
答案 1 :(得分:1)
问题相当笼统,我觉得你给出的例子与这个问题不符。
在任何非平凡的应用程序中,是的,您确实需要同步对实例变量的访问,除非您可以保证永远不会从不同的线程访问该类的实例。
关于方法和线程;方法中的局部变量驻留在堆栈上,因此本质上是线程安全的。如果该方法访问实例变量,则该方法本身不是线程安全的。
答案 2 :(得分:1)
答案取决于班级。如果方法不共享对相同实例变量的访问权限,则不需要同步。这是因为方法调用机制本身就是线程安全的,因为它不会修改对象。如果他们共享访问权限,则需要同步。以这门课为例:
class A
{
public:
void inc () { x++; }
void dec () { x--; }
private:
int x;
};
如果允许多个线程同时调用A的方法,则需要使用互斥锁保护x。有几种可能的策略。一个是使类线程安全。这看起来像这样:
class A
{
public:
void inc () {
m.lock();
x++;
m.unlock();
}
void dec () {
m.lock();
x--;
m.unlock();
}
private:
int x;
mutex m;
};
这里的优点是呼叫者不必担心同步。如果只从一个线程调用该类,则缺点是性能损失。如果您需要保证线程可以连续调用多个方法而不受另一个线程的干扰,那么您也会遇到问题。在这种情况下,调用线程需要在使用它之前查看该类。它看起来像这样:
class A
{
public:
void lock () { m.lock(); }
void unlock () { m.unlock(); }
void inc () { x++; }
void dec () { x--; }
private:
int x;
mutex m;
};
然后调用者必须在A :: lock()/ A :: unlock()对中包装方法调用。如果您需要使用未编写线程安全性的类,则需要在对象外部创建互斥锁并使用它,如上例所示。或者您可以创建一个线程安全的包装器。当然,缺点是容易出错。
请注意,您还可以同时提供锁定和解锁访问权限:
class A
{
public:
void lock () { m.lock(); }
void unlock () { m.unlock(); }
void inc_unlocked () { x++; }
void dec_unlocked () { x--; }
void inc () { m.lock(); inc_unlocked(); m.unlock(); }
void dec () { m.lock(); dec_unlocked(); m.unlock(); }
private:
int x;
mutex m;
};
这样,如果在单个线程应用程序中使用该类,则使用解锁版本进行性能,否则您将使用锁定版本或lock()/ unlock()调用中包含的未锁定版本。这是两个世界中最好的,但代价是复杂性增加。
如何在这些选项之间做出选择取决于品味和体验。
答案 3 :(得分:0)
只有在您的工作中有一些锁定和同步的互斥锁。
答案 4 :(得分:0)
如果run1()
和run2()
都没有更改a
的成员变量,或者之后从未使用过该变量,那么是的,这是安全的。一个更通用的词是无国籍。