Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of Linux multithreaded programming

2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the Linux multithreaded programming example analysis, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let Xiaobian take you to understand.

1 basic knowledge of threads

The process is the basic unit of resource management, and the thread is the basic unit of system scheduling, and the thread is the smallest unit that the operating system can schedule. It is included in the process and is the actual operation unit of the process. A thread refers to a single order of control flow in a process, where multiple threads can be concurrent in a process, and each thread performs different tasks in parallel.

A process can only do one thing at a time, and with multiple control threads, the program is designed to do more than one thing at a time, and each thread handles its own task.

It should be noted that even if the program runs on a single-core processor, you can get the benefits of the multithreaded programming model. The number of processors does not affect the program structure, so programs can be simplified through threads regardless of the number of processors.

The linux operating system uses POSIX-compliant threads as system standard threads, and the POSIX thread standard defines a complete set of API for operating threads.

two。 Thread identification

Just like a process has an ID, each thread has a thread ID, except that the process ID is unique in the whole system, while the thread is attached to the process, and its thread ID is meaningful only in the process to which it belongs. The thread ID is represented by pthread_t.

/ / pthread_self directly returns the IDinclude pthread_t pthread_self (void) of the calling thread

There is no point in determining the size of two thread ID, but sometimes it may be necessary to determine whether two given thread ID are equal, using the following interface:

/ / pthread_equal returns 0 if the thread ID specified by T1 and T2 is the same; otherwise, a non-zero value is returned. Include int pthread_equal (pthread_t T1, pthread_t T2); 3. Thread creation

The life cycle of a thread starts from the moment it is created, creating the thread's interface:

# include int pthread_create (pthread_t * thread, const pthread_attr_t * attr, void * (* start_routine) (void *), void * arg)

Function parameters:

Thread (output parameter), the thread handle returned by pthread_create after the thread is successfully created, which is used to mark the newly created thread in the API of the subsequent operation thread; start_routine (input parameter), the entry function of the new thread; arg (input parameter), the parameter passed to the entry function of the new thread; attr (input parameter), which specifies the properties of the new thread, such as thread stack size, etc. If the value is NULL, the system default property is used.

The return value of the function:

If it succeeds, it returns 0; if it fails, it returns the relevant error code.

It should be noted that:

1. The main thread, which is the initial thread of a process, whose entry function is the main function.

two。 When a new thread runs, a thread may not be executed immediately after it is created, or even after the thread that created it ends; it is also possible that the new thread is already running before the current thread is from pthread_create, or even before the new thread returns from the current thread before pthread_create.

Program example:

# include # include void printids (const char * s) {pid_t pid; pthread_t tid; pid = getpid (); tid = pthread_self (); printf ("% s, pid% lu tid% lu (0x%lx)\ n", s, (unsigned long) pid, (unsigned long) tid, (unsigned long) tid); void* thread_func (void* arg) {printids ("new thread:"); return ((void*) 0);} int main () {int err; pthread_t tid Err = pthread_create (& tid,NULL,thread_func,NULL); if (err! = 0) {fprintf (stderr, "create thread fail.\ n"); exit (- 1);} printids ("main thread:"); sleep (1); return 0;}

Note that in the above program, the main thread hibernates for one second. If it does not hibernate, the main thread does not sleep, then it may exit, so the new thread may not be run. I commented out the sleep function myself and found that it took many times for the new thread to output.

Compile command:

Gcc-o thread thread.c-lpthread

The running results are as follows:

Main thread:, pid 889 tid 139846854309696 (0x7f30a212f740) new thread:, pid 889 tid 139846845961984 (0x7f30a1939700)

You can see that the process ID of the two threads is the same. It shares resources in the process.

4. Thread termination

There are two forms of thread termination: passive termination and active termination.

There are two ways to terminate passively:

1. The termination of the process in which the thread is located, and any thread executing the exit, _ Exit, or _ exit functions, will cause the process to terminate, resulting in the termination of all threads attached to the process.

two。 Another thread calls pthread_cancel to request that the thread be canceled.

There are also two ways to terminate actively:

1. Execute the return statement in the thread's entry function, and the main function (the main thread entry function) executes the return statement, which causes the process to terminate, resulting in the termination of all threads attached to the process.

two。 The thread calls the pthread_exit function, and the main function (the main thread entry function) calls the pthread_exit function, and the main thread terminates, but if there are other threads in the process, the process will continue to exist and other threads in the process will continue to run.

Thread termination function:

Include void pthread_exit (void * retval)

A thread calling the pthread_exit function causes the calling thread to terminate and returns the content specified by retval.

Note: retval cannot point to the stack space of this thread, otherwise it may become a wild pointer!

5. Manage thread termination 5.1 thread connection

The termination of one thread is an asynchronous event for another thread. Sometimes we want to wait for an ID thread to terminate before performing certain operations. The pthread_join function provides us with this function, which is called thread connection:

Include int pthread_join (pthread_t thread, void * * retval)

Parameter description:

Thread (input parameter), which specifies the retval of the thread we want to wait (output parameter). The return value of the thread we are waiting for when it terminates is the value of return in the thread entry function or the parameter that calls the pthread_exit function.

Return value:

If it is successful, a positive error code is returned when a 0 error is returned.

When thread X connects thread Y, if thread Y is still running, thread X blocks until thread Y terminates; if thread Y is terminated before it is connected, the connection call of thread X returns immediately.

In fact, the connection thread has another meaning, after a thread terminates, if no one connects it, then the resources occupied by the terminating thread will not be recovered by the system, and the terminating thread will become a zombie thread. Therefore, when we connect to a thread, we are actually telling the system that the resources of the terminating thread can be recycled.

Note: performing a connection operation again for a thread that has already been connected will lead to unpredictable behavior!

5.2 Separation of threads

Sometimes we don't care whether a thread has terminated or not, we just hope that if a thread terminates, the system will automatically recover the resources occupied by the terminating thread. The pthread_detach function provides us with this feature, which is called thread separation:

# include int pthread_detach (pthread_t thread)

By default, a thread terminates and the system needs to be connected before the system can reclaim the resources it occupies. If we call the pthread_detach function to detach a thread, the system will automatically reclaim its resources when the thread terminates.

/ * * File name: thread_sample1.c* description: demonstrate basic thread operation * / # include # include / * child thread 1 entry function * / void * thread_routine1 (void * arg) {fprintf (stdout, "thread1: hello world!\ n"); sleep (1); / * child thread 1 exits here * / return NULL } / * Sub-thread 2 entry function * / void * thread_routine2 (void * arg) {fprintf (stdout, "thread2: iDem running...\ n"); pthread_t main_thread = (pthread_t) arg; / * separates itself and can no longer be connected to * / pthread_detach (pthread_self ()) / * determine whether the main thread ID is equal to the child thread 2ID * / if (! pthread_equal (main_thread, pthread_self ()) {fprintf (stdout, "thread2: main thread id is not equal thread2\ n");} / * wait for the main thread to terminate * / pthread_join (main_thread, NULL); fprintf (stdout, "thread2: main thread exit!\ n"); fprintf (stdout, "thread2: exit!\ n") Fprintf (stdout, "thread2: process exit!\ n"); / * child thread 2 terminates here and the process exits * / pthread_exit (NULL);} int main (int argc, char * argv []) {/ * create child thread 1thread / pthread_t T1; if (pthread_create (& T1, NULL, thread_routine1, NULL)! = 0) {fprintf (stderr, "create thread fail.\ n"); exit (- 1) } / * wait for child thread 1 to terminate * / pthread_join (T1, NULL); fprintf (stdout, "main thread: thread1 terminated!\ n\ n"); / * create child thread 2 and pass the main thread ID to child thread 2thread / pthread_t T2; if (& T2, NULL, thread_routine2, (void *) pthread_self ()! = 0) {fprintf (stderr, "create thread fail.\ n"); exit (- 1) } fprintf (stdout, "main thread: sleeping...\ n"); sleep (3); / * the main thread terminates using the pthread_exit function, and the process continues to exist * / fprintf (stdout, "main thread: exit!\ n"); pthread_exit (NULL); fprintf (stdout, "main thread: never reach here!\ n"); return 0;}

The final implementation result is as follows:

Thread1: hello Worldwide thread thread: thread1 terminatedThread main thread: sleeping...thread2: ItemThread: main thread id is not equal thread2main thread: exitthread 2: main thread exitthread thread 2: exitthread thread 2: process exit! Thank you for reading this article carefully. I hope the article "sample Analysis of Linux multithreaded programming" shared by the editor will be helpful to everyone. At the same time, I also hope that you will support and pay attention to the industry information channel. More related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report