Home > Articles > Programming > C/C++

  • Print
  • + Share This
Like this article? We recommend

Like this article? We recommend

Processes Versus Threads

Processes Versus Threads

An important issue to understand is the difference between processes and threads. A process is a heavyweight executable entity; for example, an entire program. A thread, on the other hand, is a lightweight executable entity. In fact, a thread can be spawned by a process.

The distinction between processes and threads can be important when considering deployment on a multicore platform. Say your platform has four processors—a quad-core machine. If you can build your code as four separate program instances, each instance can run as a process on its own dedicated core, but this approach may not be very efficient.

A better approach may be to break up your application and implement the key parts as threads. Then the operating system can divide the work over the quad-core platform. It's difficult to offer general advice here, but the use of a process-centric design may be suitable if you have a relatively small number of executable tasks.

Looking back at Listing 7, you can see the individual thread IDs listed. Again, C++ 0x provides facilities to help you manage threads such as t1.get_id(), where t1 is the associated thread object.

Listing 10 illustrates an excerpt from the output of the Linux command ps.

Listing 10—The Linux view of the C++ code.

ps aux
USER      PID      %CPU     %MEM  VSZ    RSS TTY   STAT       START       TIME    COMMAND
stephen   3776     0.0      0.0   27748  852 pts/0    Sl      11:39       0:00    CPlusPlus0xProject

Listing 10 provides some useful insights into the software as it executes. For instance, the TIME column indicates the amount of time for which the program has been running—the accumulated CPU time. In the context of this discussion, the item CPlusPlus0xProject in Listing 10 is a process. A related Linux command is top, an excerpt of which is shown in Listing 11.

Listing 11—A more detailed Linux view.

top - 11:51:52 up  2:50,  4 users,  load average: 0.14, 0.08, 0.06
Tasks: 179 total,   1 running, 177 sleeping,   0 stopped,   0 zombie
Cpu(s):  4.0%us,  2.3%sy,  0.0%ni, 93.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   4078892k total,  1742296k used,  2336596k free,   171180k buffers
Swap:  6384636k total,        0k used,  6384636k free,   874836k cached

Listing 11 provides a treasure trove of system information, and I strongly recommend research into its use. The load average in Listing 11 provides a time-averaged load value for the system. If the load average and the CPU utilization (4.0% in Listing 11) start to get too high, your system may not be adequate for the imposed load. For example, if the CPU utilization gets above 80%, you can be fairly sure the platform is beginning to struggle.

The Microsoft Windows Task Manager provides similar details for the Windows platform. Regardless of which platform you use, it's very important to be able to use such tools as part of development work.

C++11 and Code Migration

Given that C++11 now provides features such as multitasking support, it provides an opportunity to migrate existing code. One benefit of such migration is a potential reduction in the number of external libraries required. In other words, if you've been using a platform-specific library for thread programming, you can now consider using the C++ 0x core features as described in the preceding sections.

Conclusion

The C++11 upgrade is a good thing. It reflects the fact that C++ continues to be used many years after its first introduction in October 1985. Some features of C++11 are particularly suitable for code migration and library consolidation. The multithreading support features are very useful, and a range of options is available, including simple locks, try-fail locks, and so on. Coupled with solid design principles, there's no need for multithreaded code to suffer from race conditions or deadlocks.

The C++11 std::mutex type allows for class definitions to be made thread-safe with little effort. Indeed, making the right decision about your locking strategy can yield benefits in code performance. Just be careful not to over-engineer your code, and be sure you make use of your hard-earned domain knowledge.

Sometimes it's easier and more appropriate to use a process-oriented design, rather than writing a lot of thread support code. You're the best judge of your situation. Use the analysis facilities of your platform, whether that's Linux, Windows, Mac OS X, or whatever.

Finally, C++11 provides a useful opportunity to take stock of the libraries you use. It may be possible to substitute core calls for those currently provided by external libraries. This technique can reduce the footprint of your code and may also reduce the cost of your product.

Check out Stephen Morris' Digital Short Cut "Moving Your Career Up the Value Chain: Building Specialized Development Skills in a Global Economy."

  • + Share This
  • 🔖 Save To Your Account