Linux10: Multithreaded programming (the difference between threads and processes, basic thread functions, thread communication, synchronization and mutual exclusion)

Multithreaded programming (the difference between threads and processes, basic thread functions, thread communication, synchronization and mutual exclusion)

1. Threads and processes:

Process:
The basic unit of program execution and resource allocation in the system
(data segment, code segment and stack segment)

Thread:
Allows an application to perform multiple tasks concurrently mechanism
(lightweight process, a process within the basic scheduling unit)
multiple execution paths share concurrent process memory space, the shared resource processes:
executing program code
segment:
initialization data segment
is not Initialize the data segment
Heap space
Stack space (independent)
file descriptor
Follow the posix thread interface, called pthread
requires the header pthread.h file, link libpthread.a
pthread is not a library of the linux system

Process -> Thread:
linux2.2 kernel fork creates light process, up to 4096, 2.4 kernel eliminates the limit of number

The difference between thread and process:
Process has an independent address space, and thread does not have a separate address space. (Threads in the same process share the address space of the process)

Why introduce threads:

The space spent to start a process is much larger than the space spent to start a thread (about 30 times), and the time required to switch between threads is much less than the time required to switch between processes (>10 times)
maintenance The process consumes much more kernel than threads ------ process table
data can be shared between threads, making communication easier

Process VS thread:

Insert picture description here

How to choose threads and processes:

1) Priority threads that
need to be created and destroyed frequently 2) Priority threads that require a lot of calculations.
Consider switching time-consuming and laborious, affecting computational efficiency.
3) Strongly related processing threads, weakly related processing processes
4) May be extended to Use processes for multi-machine distribution and threads for multi-core distribution.
5) When all requirements are met, use the method you are most familiar with and best at

2. Thread basic functions:

2.1: Thread creation:

create:

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

Restrict is introduced by the C99 standard. It can only be used to limit and constrain pointers and indicate that pointers are the only and initial way to access a data object. That is, it tells the compiler that all operations that modify the contents of the memory pointed to by the pointer are It must be modified through the pointer, but not through other means (other variables or pointers); the advantage of this is that it can help the compiler to better optimize the code and generate more efficient assembly code. Such as int *restrict The memory unit pointed to by ptr, ptr can only be accessed by ptr, and any other pointers that also point to this memory unit are undefined, and the blunt point is an invalid pointer. The emergence of restrict is due to the inherent flaws of the C language. C programmers should actively avoid this flaw, and the compiler will also optimize your code very cooperatively.
Parameters:

Thread ID //unsigned long (pthread_t)

Thread attributes: // NULL

Binding attributes:
binding
a user thread to a kernel thread fixedly, the scheduling of CPU time slices is for kernel threads (that is, lightweight processes), threads with binding attributes can guarantee that there is always one when needed Kernel thread corresponds to it.
Unbound. The
relationship between user thread and kernel thread is not always fixed. The system controls the allocation.

Separation attribute:
Used to determine how a thread terminates itself.
Separation. When
a thread ends, it immediately releases the system resources it occupied.
Non-separation
. The system resources occupied by the thread are not released, that is, there is no real termination. Only when the pthread_join() function returns, the created thread can release its own system resources

Thread entry function:
parameters passed to the thread entry function

Return value:
return 0 on success, error code on failure

2.2: The identification of the thread:

thread_t pthread_self(void);
Get thread ID
unsigned long int --%lu

2.3: The exit of the thread:

void pthread_exit(void *value_ptr);
Thread exit
Normal exit
Abnormal exit
Parameters:
save the state of thread exit

2.4: Thread waiting (connection):

int pthread_join(pthread_t thread, void **value_ptr);
wait for the specified thread to exit.
Parameter
The thread ID to wait for
saves the state of thread exit. Generally specify NULL to
receive the value of pthread_exit or return

2.6: Cancellation of thread:

int pthread_cancel(pthread_t thread);
cancel a thread that has not run out

2.7: Thread attributes:

initialization:
int pthread_attr_init(pthread_attr_t *attr);
attr: thread attribute
success: 0 error: -1
Set binding properties:
int pthread_attr_setscope(pthread_attr_t *attr, int scope);
PTHREAD_SCOPE_SYSTEM: bound
PTHREAD_SCOPE_PROCESS: unbound
success: 0 error: -1
Set thread separation properties:
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
PTHREAD_CREATE_DETACHED: detached
PTHREAD _CREATE_JOINABLE: non-detached
success: 0 error: -1

2.8: Thread cleaning:

Resource release:

 void pthread_cleanup_push(void (*routine)(void*), void *arg);
  void pthread_cleanup_pop(int execute);

parameter:

routine: the pointer of the function to register the cleanup
arg: the parameter passed to the cleanup function
execute: determine whether the cleanup function is called
0-not called
non 0-called

note: Adopts first-in-last-out stack structure management, the termination actions in the program segment between the two functions (including calling pthread_exit() and abnormal termination (other processes use pthread_cancel to cancel the current process) without return) will be executed

3: Communication between threads:

1. Share process resources directly (using global variables)
2. Signal (same process):
pthread_kill();-------- kill

4: Synchronization and mutual exclusion:

4.1: Why do synchronization and mutual exclusion:

Realize the protection and monopoly of resources

4.2: Synchronous and mutually exclusive operations:

4.2.1: Mutually exclusive semaphore (signal lock):

Install the required libraries:

apt-get install manpages-posix-dev

Meaning:
Mutex locks are regarded as global variables in a certain sense.
Each time the resource is operated, the lock is detected by default. If the lock is in the locked state, wait for the lock to be unlocked.
If the lock is in the unlocked state, use the lock. Unlock.
Category:
Fast mutex
most common locks, in line with the above meaning of
detecting lock
fast non-blocking versions of the mutex
recursive locks
repeatedly locked
using the process:

Mutex initialization: pthread_mutex_init
mutex lock: pthread_mutex_lock
mutex judgment lock: pthread_mutex_trylock
mutex unlock: pthread_mutex_unlock
elimination mutex lock: pthread_mutex_destroy

Mutual exclusion lock API:
creation:
dynamic creation:
pthread_mutex_init
parameter 1: variable describing the lock pthread_mutex_t mutex;

Parameter 2: Specify the type of lock:
Default NULL means to create a fast mutex
PTHREAD_MUTEX_INITIALIZER: Create a fast mutex
function input value Mutexattr PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: Create a recursive mutex
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: Create an error detection mutex

Statically created:

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
//静态创建快速互斥锁

Lock
int pthread_mutex_lock(pthread_mutex_t *mutex);//If you succeed in locking, you will wait for
int pthread_mutex_trylock(pthread_mutex_t *mutex); if you
succeed in locking, you will return an error if unsuccessful-non-blocking
unlock
int pthread_mutex_unlock(pthread_mutex_t *mutex);
destroy the lock
int pthread_mutex_destroy(pthread_mutex_t *mutex);
Minor defects:
Beware of deadlocks: In the same thread, the first lock is no problem, and then there is no unlock, and then lock again, it will block, and it will block forever

4.2.2: Condition variables:

Meaning:
When a condition is not met, the program will be blocked, and the condition can be unblocked when the condition is met.
Related API:
Create:
Static mode

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

Dynamic way

int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
  没有满足条件阻塞
int pthread_cond_wait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex);
 满足条件解除阻塞
int pthread_cond_signal(pthread_cond_t *cond);

destroy

  int pthread_cond_destroy(pthread_cond_t *cond);

4.2.3: Semaphore (signal light):

Meaning:
The semaphore of the thread, which is different from the signal in the process, is
essentially a non-negative integer counter, used to control the access to common resources. The
principle:
P operation decrements sem by one, and V operation increases sem by one. When the value of the semaphore sem is greater than or equal to zero, the process (or thread) has access to public resources-the mutually exclusive synchronization
semaphore related API:
create:

int sem_init(sem_t *sem, int pshared, unsigned int value);

Create a semaphore sem, the initial value is value pshared: specified as 0
pshared: determine whether the semaphore can be shared among several processes. Since Linux has not yet implemented the sharing of semaphores between processes, this value can only be taken as 0 to
obtain the semaphore value:

int sem_getvalue(sem_t *sem, int *sval);

Cost -1:

 int sem_wait(sem_t *sem);---阻塞
 int sem_trywait(sem_t *sem);--非阻塞
 释放 +1:
 int sem_post(sem_t *sem);

Clean up:

 sem_destroy(sem_t *sem);

Precautions:

If you use synchronization and mutual exclusion, all threads must follow this operation, otherwise it is meaningless

Guess you like

Origin blog.csdn.net/weixin_40734514/article/details/109254157