Thread technology was proposed as early as 1960s, but the real application of multithreading to the operating system was in the middle of 1980s, and Solaris was a leader in this field. Traditional UNIX also supports the concept of thread, but only one thread is allowed in a process, so multithreading means multi-process.
Now, multithreading technology has been supported by many operating systems, including Windows/NT and, of course, Linux.
Why do we need to introduce threads after the concept of a process is introduced? What are the advantages of multithreading? What systems should adopt multithreading? We must answer these questions first.
One of the reasons for using multithreading is that compared with processes, it is a very "frugal" multi-task operation method. We know that in a Linux system, starting a new process must be allocated to it with an independent address space, creating a large number of data tables to maintain its code segment, stack segment, and data segment, this is an "expensive" way of multitasking. While multiple threads running in a process use the same address space for each other to share most of the data. The space required to start a thread is much less than the space required to start a process, in addition, the time required for switching between threads is much less than the time required for switching between processes. According to statistics, in general, the overhead of a process is about 30 times the overhead of a thread. Of course, this data may be quite different in a specific system.
The second reason for using multithreading is the convenient communication mechanism between threads. For different processes, they have independent data space, and data transmission can only be performed through communication. This method is not only time-consuming, but also inconvenient. The thread is not the case. Because the threads in the same process share data space, the data of one thread can be directly used by other threads, which is fast and convenient. Of course, data sharing also brings about other problems. Some Variables cannot be modified by two threads at the same time, and some subprograms declare static data, which is more likely to cause catastrophic damage to multithreaded programs, these are the things you need to pay attention to when writing multi-threaded programs.
In addition to the advantages mentioned above, multi-threaded programs, as a multi-task and concurrent working method, certainly have the following advantages:
1) Improve application response. This is especially meaningful for graphic interface programs. When an operation takes a long time, the entire system will wait for this operation. At this time, the program will not respond to keyboard, mouse, and menu operations, but will use multithreading technology, putting time consuming in a new thread can avoid this embarrassing situation.
2) Make the multi-CPU system more effective. The operating system ensures that different threads run on different CPUs when the number of threads is not greater than the number of CPUs.
3) Improve the program structure. A long and complex process can be considered to be divided into multiple threads and become several independent or semi-independent running parts. Such a program will facilitate understanding and modification.
Next we will try to write a simple multi-threaded program.
Simple multi-thread programming
Multithreading in Linux follows the POSIX thread interface, which is called pthread. To compile a multi-threaded program in Linux, you need to use the header file pthread. H. You need to use the library libpthread. A for connection. By the way, the implementation of pthread in Linux is achieved by calling clone. Clone () is a Linux-specific system call. It is used in a similar way as fork. For details about clone (), interested readers can refer to the relevant documentation. The following shows a simple multi-threaded program pthread_create.c.
An important thread creates a function prototype:
# Include <pthread. h>
Int pthread_create (pthread_t * restrict TIDP, const pthread_attr_t * restrict ATTR, void * (* start_rtn) (void), void * restrict Arg );
Returned value: If a thread is successfully created, 0 is returned. Otherwise, the error number is returned.
Format parameters:
Pthread_t * restrict TIDP indicates the thread ID pointer of the thread to be created
Const pthread_attr_t * restrict ATTR specifies the thread attributes when a thread is created.
Void * (start_rtn) (void) returns a void pointer function.
Void * restrict Arg start_rtn row Parameter
Example 1:
Function: create a simple thread
Program name: pthread_create.c
/*************************************** **************************************** *************
** Name: pthread_create.c
** Used to study the multithread programming in Linux OS
** Author: zeickey
** Date: 2006/9/16
** Copyright (c) 2006, all rights reserved!
**************************************** **************************************** *************/
# Include <stdio. h>
# Include <pthread. h>
Void * mythread1 (void)
{
Int I;
For (I = 0; I <100; I ++)
{
Printf ("This is the 1st pthread, created by zieckey./N ");
Sleep (1); // Let this thread to sleep 1 second, and then continue to run
}
}
Void * mythread2 (void)
{
Int I;
For (I = 0; I <100; I ++)
{
Printf ("this is the 2st pthread, created by zieckey./N ");
Sleep (1 );
}
}
Int main ()
{
Int I = 0, ret = 0;
Pthread_t id1, Id2;
Ret = pthread_create (& Id2, null, (void *) mythread1, null );
If (RET)
{
Printf ("create pthread error! /N ");
Return 1;
}
Ret = pthread_create (& Id2, null, (void *) mythread2, null );
If (RET)
{
Printf ("create pthread error! /N ");
Return 1;
}
Pthread_join (id1, null );
Pthread_join (Id2, null );
Return 0;
}
We compile this program:
# GCC pthread_create.c-lpthread
Because the pthread library is not a Linux system library, you must add-lpthread during compilation. Otherwise, the compilation will fail and the following error will occur.
Thread_test.c: In the 'create' function:
Thread_test.c: 7: Warning: In a function with a returned value, the program flow reaches the end of the function.
/Tmp/ccobjmud. O: In function 'main': thread_test.c :(. Text + 0x4f): Undefined reference to 'pthread _ create'
Collect2: LD returns 1
Run:
#./A. Out
This is the 1st pthread, created by zieckey.
This is the 2st pthread, created by zieckey.
This is the 1st pthread, created by zieckey.
This is the 2st pthread, created by zieckey.
This is the 2st pthread, created by zieckey.
This is the 1st pthread, created by zieckey.
....
The two threads run alternately.
This example describes how to create a thread.
The following example describes how to pass parameters to a thread.
Example 2:
Function: transmits an integer value to a new thread.
Program name: pthread_int.c
/*************************************** **************************************** *************
** Name: pthread_int.c
** Used to study the multithread programming in Linux OS
** Pass a parameter to the thread.
** Author: zeickey
** Date: 2006/9/16
** Copyright (c) 2006, all rights reserved!
**************************************** **************************************** *************/
# Include <stdio. h>
# Include <pthread. h>
# Include <unistd. h>
Void * Create (void * Arg)
{
Int * num;
Num = (int *) ARG;
Printf ("create parameter is % d/N", * num );
Return (void *) 0;
}
Int main (INT argc, char * argv [])
{
Pthread_t TIDP;
Int error;
Int test = 4;
Int * ATTR = & test;
Error = pthread_create (& TIDP, null, create, (void *) ATTR );
If (error)
{
Printf ("pthread_create is created is not created.../N ");
Return-1;
}
Sleep (1 );
Printf ("pthread_create is created.../N ");
Return 0;
}
Compilation Method:
Gcc-lpthread pthread_int.c-wall
Execution result:
Create parameter is 4
Pthread_create is created...
Summary of routine:
We can see that the entire row pointer passed in the main function is passed to the new thread function.
In the preceding example, we can see that int data of another thread is transferred to the new thread, and strings or more complex data structures can be transferred between threads.
Example 3:
Program function: pass a string to the new thread
Program name: pthread_string.c
/*************************************** **************************************** *************
** Name: pthread_string.c
** Used to study the multithread programming in Linux OS
** Pass a 'Char * 'parameter to the thread.
** Author: zeickey
** Date: 2006/9/16
** Copyright (c) 2006, all rights reserved!
**************************************** **************************************** *************/
# Include <pthread. h>
# Include <stdio. h>
# Include <unistd. h>
Void * Create (void * Arg)
{
Char * Name;
Name = (char *) ARG;
Printf ("the parameter passed from main function is % s/n", name );
Return (void *) 0;
}
Int main (INT argc, char * argv [])
{
Char * A = "zieckey ";
Int error;
Pthread_t TIDP;
Error = pthread_create (& TIDP, null, create, (void *) );
If (error! = 0)
{
Printf ("pthread is not created./N ");
Return-1;
}
Sleep (1 );
Printf ("pthread is created.../N ");
Return 0;
}
Compilation Method:
Gcc-wall pthread_string.c-lpthread
Execution result:
The parameter passed from main function is zieckey
Pthread is created...
Summary of routine:
It can be seen that the string in the main function is passed into the new thread.
Example 4:
Program function: pass a string to the new thread
Program name: pthread_struct.c
/*************************************** **************************************** *************
** Name: pthread_struct.c
** Used to study the multithread programming in Linux OS
** Pass a 'Char * 'parameter to the thread.
** Author: zeickey
** Date: 2006/9/16
** Copyright (c) 2006, all rights reserved!
**************************************** **************************************** *************/
# Include <stdio. h>
# Include <pthread. h>
# Include <unistd. h>
# Include <stdlib. h>
Struct menber
{
Int;
Char * s;
};
Void * Create (void * Arg)
{
Struct menber * temp;
Temp = (struct menber *) ARG;
Printf ("menber-> A = % d/N", temp-> );
Printf ("menber-> S = % s/n", temp-> S );
Return (void *) 0;
}
Int main (INT argc, char * argv [])
{
Pthread_t TIDP;
Int error;
Struct menber * B;
B = (struct menber *) malloc (sizeof (struct menber ));
B-> A = 4;
B-> S = "zieckey ";
Error = pthread_create (& TIDP, null, create, (void *) B );
If (error)
{
Printf ("phread is not created.../N ");
Return-1;
}
Sleep (1 );
Printf ("pthread is created.../N ");
Return 0;
}
Compilation Method:
Gcc-wall pthread_struct.c-lpthread
Execution result:
Menber-> A = 4
Menber-> S = zieckey
Pthread is created...
Summary of routine:
It can be seen that a struct in the main function is passed into the new thread.
The thread contains information required to identify the execution environment in the process. It integrates all information in the process to share threads, including the global memory and heap memory of text programs and programs, stacks, and file descriptors.
Example 5:
Purpose: To verify that a new thread can share data in a process
Program name: pthread_0000.c
/*************************************** **************************************** *************
** Name: pthread_share_data.c
** Used to study the multithread programming in Linux OS
** Pass a 'Char * 'parameter to the thread.
** Author: zeickey
** Date: 2006/9/16
** Copyright (c) 2006, all rights reserved!
**************************************** **************************************** *************/
# Include <stdio. h>
# Include <pthread. h>
# Include <unistd. h>
Static int A = 4;
Void * Create (void * Arg)
{
Printf ("New pthread.../N ");
Printf ("A = % d/N", );
Return (void *) 0;
}
Int main (INT argc, char * argv [])
{
Pthread_t TIDP;
Int error;
A = 5;
Error = pthread_create (& TIDP, null, create, null );
If (error! = 0)
{
Printf ("New thread is not create.../N ");
Return-1;
}
Sleep (1 );
Printf ("New thread is created.../N ");
Return 0;
}
Compilation Method:
Gcc-wall pthread_share_data.c-lpthread
Execution result:
New pthread...
A = 5
New thread is created...
Summary of routine:
As you can see, when the main thread changes the value of global variable A, the new thread prints the changed value, we can see that the data information in the process where the thread is located can be accessed.
2. Thread termination
If any thread in the process calls exit, _ exit, or _ exit, the whole process will be terminated,
Similarly, if the default signal action is to terminate the process, sending the signal to the thread will terminate the process.
Normal thread exit mode:
(1) The thread only returns from the startup routine. The returned value is the exit code in the thread.
(2) The thread can be terminated by another process.
(3) The thread calls the pthread_exit function by itself.
Two important function prototypes:
# Include <pthread. h>
Void pthread_exit (void * rval_ptr );
/* Pointer returned when the rval_ptr thread exits */
Int pthread_join (pthread_t thread, void ** rval_ptr );
/* Process ended successfully is 0; otherwise, the process is incorrectly encoded */
Routine 6
Purpose: The thread Exits normally and receives the return code of the thread exit.
Program name: pthread_exit.c
/*************************************** **************************************** *************
** Name: pthread_exit.c
** Used to study the multithread programming in Linux OS
** A example showing a thread to exit and with a return code.
** Author: zeickey
** Date: 2006/9/16
** Copyright (c) 2006, all rights reserved!
**************************************** **************************************** *************/
# Include <stdio. h>
# Include <pthread. h>
# Include <unistd. h>
Void * Create (void * Arg)
{
Printf ("New thread is created.../N ");
Return (void *) 8;
}
Int main (INT argc, char * argv [])
{
Pthread_t tid;
Int error;
Void * temp;
Error = pthread_create (& tid, null, create, null );
If (error)
{
Printf ("thread is not created.../N ");
Return-1;
}
Error = pthread_join (TID, & temp );
If (error)
{
Printf ("thread is not exit.../N ");
Return-2;
}
Printf ("thread is exit code % d/N", (INT) temp );
Return 0;
}
Compilation Method:
Gcc-wall pthread_exit.c-lpthread
Execution result:
New thread is created...
Thread is exit code 8
Summary of routine:
It can be seen that the int value of the thread can be returned when the thread exits. When a thread exits, it not only returns the int value of the thread, but also a complex data structure.
Routine 7
Program objective: to return a complex data structure after the thread ends
Program name: pthread_return_struct.c
# Include <stdio. h>
# Include <pthread. h>
# Include <unistd. h>
Struct menber
{
Int;
Char * B;
} Temp = {8, "zieckey "};
Void * Create (void * Arg)
{
Printf ("New thread.../N ");
Return (void *) & temp;
}
Int main (INT argc, char * argv [])
{
Int error;
Pthread_t tid;
Struct menber * C;
Error = pthread_create (& tid, null, create, null );
If (error)
{
Printf ("New thread is not created.../N ");
Return-1;
}
Printf ("Main.../N ");
Error = pthread_join (TID, (void *) & C );
If (error)
{
Printf ("New thread is not exit.../N ");
Return-2;
}
Printf ("C-> A = % d/N", C-> );
Printf ("C-> B = % s/n", C-> B );
Sleep (1 );
Return 0;
}
Compilation Method:
Gcc-wall pthread_return_struct.c-lpthread
Execution result:
Main...
New thread...
C-> A = 8
C-> B = zieckey
Summary of routine:
Remember to apply the returned data structure when the structure to be returned is not released,
If the data structure has changed, the returned data will not be what we need, but dirty data.
3. Thread ID
Function prototype:
# Include <pthread. h>
Pthread_t pthread_self (void );
Pid_t getpid (void );
Getpid () is used to obtain the process identifier of the current process. Function Description
Routine 8
Purpose: To print the thread ID and process ID in the newly created thread
Program name: pthread_id.c
/*************************************** **************************************** *************
** Name: pthread_id.c
** Used to study the multithread programming in Linux OS.
** Showing how to get the thread's tid and the process's PID.
** Author: zeickey
** Date: 2006/9/16
** Copyright (c) 2006, all rights reserved!
**************************************** **************************************** *************/
# Include <stdio. h>
# Include <pthread. h>
# Include <unistd. h>/* getpid ()*/
Void * Create (void * Arg)
{
Printf ("New thread.../N ");
Printf ("this thread's ID is % u/N", (unsigned INT) pthread_self ());
Printf ("the process PID is % d/N", getpid ());
Return (void *) 0;
}
Int main (INT argc, char * argv [])
{
Pthread_t tid;
Int error;
Printf ("main thread is starting.../N ");
Error = pthread_create (& tid, null, create, null );
If (error)
{
Printf ("thread is not created.../N ");
Return-1;
}
Printf ("the main process's PID is % d/N", getpid ());
Sleep (1 );
Return 0;
}
Compilation Method:
Gcc-wall-lpthread pthread_id.c
Execution result:
Main thread is starting...
The main process's PID is 3307
New thread ....
This thread's ID is 3086347152
The process PID is 3307 published on ZZ reading (1141) Comments (1) EDIT favorites Reference Category: Linux C Programming
Comment
# Re: LINUX multi-thread programming details [not logged on] ret = pthread_create (& Id2, null, (void *) mythread1, null );
If (RET)
{
Printf ("create pthread error! /N ");
Return 1;
}
The code in Example 1 is incorrect.
Ret = pthread_create (& Id2, null, (void *) mythread1, null );
It should be
Ret = pthread_create (& id1, null, (void *) mythread1, null );