C++多线程中的对象

发布于 2024-11-25 08:22:30 字数 552 浏览 0 评论 0原文

我想询问当类的单个实例/对象在不同线程之间共享时,C++ 中的线程安全性(例如使用带有 C++ 包装器的 POSIX 线程)。例如,A 类的单个对象的成员方法将在不同的线程中调用。关于线程安全我应该/可以做什么?

class A {
    private:

    int n;

    public:

    void increment()
    {
        ++n;
    }

    void decrement()
    {
        --n;
    }
};
  • 我应该用锁或其他东西来保护增量/减量方法中的类成员 n 吗?还有静态(类变量)成员也有这样的锁需求吗?
  • 如果成员是不可变的,我就不必担心,对吗?
  • 有什么是我现在无法预见的吗?

除了多线程中单个对象的场景之外,多线程中的多个对象又如何呢?每个线程都拥有一个类的实例。除了静态(类变量)成员之外还有什么特别的吗?

这些是我的想法,但我相信这是一个很大的话题,如果您有良好的资源并参考之前的讨论,我会很高兴。

问候

I would like to ask about thread safety in C++ (using POSIX threads with a C++ wrapper for ex.) when a single instance/object of a class is shared between different threads. For example the member methods of this single object of class A would be called within different threads. What should/can I do about thread safety?

class A {
    private:

    int n;

    public:

    void increment()
    {
        ++n;
    }

    void decrement()
    {
        --n;
    }
};
  • Should I protect class member n within increment/decrement methods with a lock or something else? Also static (class variables) members have such a need for lock?
  • If a member is immutable, I do not have to worry about it, right?
  • Anything that I cannot foreseen now?

In addition to the scenario with a single object within multithreads, what about multiple object with multiple threads? Each thread owns an instance of a class. Anything special other than static (class variables) members?

These are the things in my mind, but I believe this is a large topic and I would be glad if you have good resources and refer previous discussions about that.

Regards

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

十级心震 2024-12-02 08:22:30

建议:不要尝试用手做。使用一个好的多线程库,例如 Boost 中的库: http:// www.boost.org/doc/libs/1_47_0/doc/html/thread.html

英特尔的这篇文章将为您提供一个很好的概述:http://software.intel.com/en-us/文章/多线程应用程序的多种方法/

Suggestion: don't try do it by hand. Use a good multithread library like the one from Boost: http://www.boost.org/doc/libs/1_47_0/doc/html/thread.html

This article from Intel will give you a good overview: http://software.intel.com/en-us/articles/multiple-approaches-to-multithreaded-applications/

迷荒 2024-12-02 08:22:30

这是一个非常大的主题,可能不可能在本线程中完成该主题。
黄金法则是“当别人在写作时你不能阅读”。
因此,如果您有一个共享变量的对象,则必须在访问共享变量的函数中放置一个锁。

很少有情况并非如此。
第一种情况是对于整数,您可以使用原子函数,如 c-smile 所示,在这种情况下,CPU 将在缓存上使用硬件锁,因此其他内核无法修改变量。
第二种情况是无锁队列,它是一种特殊的队列,使用比较和交换功能来保证指令的原子性。

所有其他案件都必须锁定......
第一种方法是锁定所有内容,当涉及更多对象时,这可能会导致很多问题(ObjA 尝试从 ObjB 读取,但是 ObjB 正在使用该变量,并且也在等待 ObjC 等待 ObjA)。无限期等待(死锁)。

更好的方法是最小化线程共享变量的点。
例如,如果您有数据数组,并且想要并行化数据计算,您可以启动两个线程,线程一将仅在偶数索引上工作,而线程二将在奇数索引上工作。线程正在处理同一组数据,但只要数据不重叠,就不必使用锁。 (这称为数据并行化)

另一个方法是将应用程序组织为一组“工作”(在线程上运行并产生结果的函数),并使工作仅与消息进行通信。您只需要实现一个线程安全的消息系统和一个工作调度程序就完成了。或者你可以使用像intel TBB这样的libray。

这两种方法都不能解决死锁问题,但可以让您隔离问题并更轻松地发现错误。多线程中的错误确实很难调试,有时也很难发现。

因此,如果您正在学习,我建议您从 ry 开始并从 pThread 开始,然后当您学习了基础知识后,请转向用户更友好的库(例如 boost),或者如果您使用 Gcc 4.6 作为编译器,请使用 C++0x std: :线

It's a really large topic and probably it's impossible to complete the topic in this thread.
The golden rule is "You can't read while somebody else is writing."
So if you have an object that share a variable you have to put a lock in the function that access the shared variable.

There are very few cases when this is not true.
The first case is for integer number you can use the atomic function as showed by c-smile, in this case the CPU will use an hardware lock on the cache, so other cores can't modify the variables.
The second cases are lock free queue, that are special queue that use the compare and excange function to assure the atomicity of the instruction.

All the other cases are MUST be locked...
the first aproach is to lock everything, this can lead to a lot of problem when more object are involved (ObjA try to read from ObjB but, ObjB is using the variable and also is waiting for ObjC that wait ObjA) Where circular lock can lead to indefinite waiting (deadlock).

A better aproach is to minimize the point where thread share variable.
For example if you have and array of data, and you want to parallelize the computation on the data you can launch two thread and thread one will work only on even index while thread two will work on the odd. The thread are working on the same set of data, but as long the data don't overlap you don't have to use lock. (This is called data parallelization)

The other aproch is to organize the application as a set of "work" (function that run on a thread a produce a result) and make the work communicate only with messages. You only have to implement a thread safe message system and a work sheduler you are done. Or you can use libray like intel TBB.

Both approach don't solve deadlock problem but let you isolate the problem and find bugs more easily. Bugs in multithread are really hard to debug and sometime are also difficoult to find.

So, if you are studing I suggest to start with the thery and start with pThread, then whe you are learned the base move to a more user frendly library like boost or if you are using Gcc 4.6 as compiler the C++0x std::thread

无人问我粥可暖 2024-12-02 08:22:30
  • 是的,如果在多线程环境中使用函数,则应该使用锁来保护它们。您可以使用 Boost 库

  • 和是的,不可变成员不应该成为问题,因为这样的成员一旦初始化就无法更改。

关于“具有多个线程的多个对象”..这很大程度上取决于您想要做什么,在某些情况下您可以使用 线程池这是一种机制,它有一定数量的线程等待作业进入。但是没有线程并发,因为每个线程只做一项工作。

  • yes, you should protect the functions with a lock if they are used in a multithreading environment. You can use boost libraries

  • and yes, immutable members should not be a concern, since a such a member can not be changed once it has been initialized.

Concerning "multiple object with multiple threads".. that depends very much of what you want to do, in some cases you could use a thread pool which is a mechanism that has a defined number of threads standing by for jobs to come in. But there's no thread concurrency there since each thread does one job.

去了角落 2024-12-02 08:22:30

你必须保护柜台。没有其他选择。

在 Windows 上,您可以使用以下函数来执行此操作:

#if defined(PLATFORM_WIN32_GNU)

  typedef long counter_t;
  inline long _inc(counter_t& v)               {    return InterlockedIncrement(&v);  }
  inline long _dec(counter_t& v)               {    return InterlockedDecrement(&v);  }
  inline long _set(counter_t &v, long nv)      {    return InterlockedExchange(&v, nv);  }

#elif defined(WINDOWS) && !defined(_WIN32_WCE) // lets try to keep things for wince simple as much as we can

  typedef volatile long counter_t;
  inline long _inc(counter_t& v)               {    return InterlockedIncrement((LPLONG)&v);  }
  inline long _dec(counter_t& v)               {    return InterlockedDecrement((LPLONG)&v);  }
  inline long _set(counter_t& v, long nv)      {    return InterlockedExchange((LPLONG)&v, nv);  }

You have to protect counters. No other options.

On Windows you can do this using these functions:

#if defined(PLATFORM_WIN32_GNU)

  typedef long counter_t;
  inline long _inc(counter_t& v)               {    return InterlockedIncrement(&v);  }
  inline long _dec(counter_t& v)               {    return InterlockedDecrement(&v);  }
  inline long _set(counter_t &v, long nv)      {    return InterlockedExchange(&v, nv);  }

#elif defined(WINDOWS) && !defined(_WIN32_WCE) // lets try to keep things for wince simple as much as we can

  typedef volatile long counter_t;
  inline long _inc(counter_t& v)               {    return InterlockedIncrement((LPLONG)&v);  }
  inline long _dec(counter_t& v)               {    return InterlockedDecrement((LPLONG)&v);  }
  inline long _set(counter_t& v, long nv)      {    return InterlockedExchange((LPLONG)&v, nv);  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文