Linux thread-Mutex mutexes and semaphore mutexes notes

Multi-threaded development has mature pthread library support on Linux platform. The most basic concepts involved in multi-threaded development mainly include three points: threads, mutual exclusion locks, and conditions. Among them, thread operations are divided into three types: thread creation, exit, and waiting. Mutex includes 4 operations, namely creation, destruction, locking and unlocking. There are five types of conditional operations: create, destroy, trigger, broadcast and wait. Some other thread extension concepts, such as semaphores, can be encapsulated through the basic operations of the three basic elements above. See the table below for details:
Insert picture description here

Thread creation API

#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号

When pthread_create returns successfully, the memory unit pointed to by tidp is set to the thread ID of the newly created thread. The attr parameter is used to customize various thread attributes. You can temporarily set it to NULL to create threads with default attributes.

The newly created thread runs from the address of the start_rtn function, which has only one untyped pointer parameter arg. If you need to pass more than one parameter to the start_rtn function, you need to put these parameters in a structure, and then pass in the address of this structure as the arg parameter.

2. Thread exit

A single thread can exit in the following three ways to stop its control flow without terminating the entire process:

1) The thread just returns from the startup routine, and the return value is the thread's exit code.

2) A thread can be cancelled by other threads in the same process.

3) The thread calls pthread_exit:

#include <pthread.h>
int pthread_exit(void *rval_ptr);
  rval_ptr是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。

3. Thread waiting

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否则返回错误编号

The thread calling this function will block until the specified thread calls pthread_exit, returns from the startup routine, or is cancelled. If the routine just returns i from its startup routine, rval_ptr will contain the return code. If the thread is cancelled, the memory unit specified by rval_ptr is set to PTHREAD_CANCELED.

You can automatically put the thread in the detached state by calling pthread_join, so that the resource can be restored. If the thread is already in the detached state, the pthread_join call will fail and return EINVAL.

If you are not interested in the return value of the thread, you can set rval_ptr to NULL. In this case, calling the pthread_join function will wait for the specified thread to terminate, but will not get the thread's termination status.

4. Thread detach

A thread is either joinable (default) or detached. When a joinable thread terminates, its thread ID and exit status will be stored in another thread to call pthread_join on it. The detached threads are like daemons. When they terminate, all related resources are released, and we cannot wait for them to terminate. If one thread needs to know when another thread terminates, it is best to keep the second thread in a confluent state.

The pthread_detach function turns the specified thread into a detached state.

#include <pthread.h>
int pthread_detach(pthread_t thread);
// 返回:若成功返回0,否则返回错误编号
  本函数通常由想让自己脱离的线程使用,就如以下语句:

pthread_detach(pthread_self());

5. Thread ID acquisition and comparison

#include <pthread.h>
pthread_t pthread_self(void);
// 返回:调用线程的ID
  对于线程ID比较,为了可移植操作,我们不能简单地把线程ID当作整数来处理,因为不同系统对线程ID的定义可能不一样。我们应该要用下边的函数:
#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);
// 返回:若相等则返回非0值,否则返回0

For multithreaded programs, we often need to synchronize these multithreads. Synchronization refers to allowing only a certain thread to access a certain resource within a certain period of time. During this time, other threads are not allowed to access the resource. We can synchronize resources through mutex, condition variable, and reader-writer lock. Here, we will not introduce read-write locks.

API related to mutex lock

A mutex is essentially a lock, which locks the mutex before accessing shared resources, and releases the lock on the mutex after the access is completed. After locking the mutex, any other thread that tries to lock the mutex again will be blocked until the current thread releases the mutex. If multiple threads are blocked when the mutex is released, all blocked threads on the mutex will become runnable. The first thread that becomes runnable can lock the mutex, and other threads will You will see that the mutex is still locked, and you can only go back and wait for it to become available again. In this way, only one thread can run forward at a time.

It is necessary to specify that all threads must comply with the same data access rules during design. Only in this way can the mutual exclusion mechanism work properly. The operating system does not serialize data access. If one of the threads is allowed to access the shared resource without obtaining the lock, even if the other threads acquire the lock before using the shared resource, there will still be data inconsistencies.

Mutex variables are represented by the pthread_mutex_t data type. It must be initialized before using the mutex variable. It can be set to the constant PTHREAD_MUTEX_INITIALIZER (only for statically allocated mutex), or it can be initialized by calling the pthread_mutex_init function. If the mutex is allocated dynamically (for example, by calling the malloc function), then pthread_mutex_destroy needs to be called before the memory is released.

1. Create and destroy mutex

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号
  要用默认的属性初始化互斥量,只需把attr设置为NULL。  

2. Lock and unlock

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t mutex);
int pthread_mutex_trylock(pthread_mutex_t mutex);
int pthread_mutex_unlock(pthread_mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号

Thread Mutex Mutex Example

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>

//由于线程共享进程的资源和地址空间,因此在对这些资源进行操作时,必须考虑到线程间资源访问的惟一性问题


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;   //快速互斥锁

int lock_var;
time_t end_time;

void pthread1 ( void *arg );
void pthread2 ( void *arg );

int main ( int argc, char *argv[] )
{
    
    
	pthread_t id1,id2;
	
	int ret;

	end_time = time ( NULL ) +10;

	ret=pthread_create ( &id1,NULL, ( void * ) pthread1, NULL );
	if ( ret!=0 )
		perror ( "pthread cread1" );
	ret=pthread_create ( &id2,NULL, ( void * ) pthread2, NULL );
	if ( ret!=0 )
		perror ( "pthread cread2" );
	
	pthread_join ( id1,NULL );
	pthread_join ( id2,NULL );
	pthread_mutex_destroy(&mutex);
	exit ( 0 );
}

void pthread1 ( void *arg )
{
    
    
	int i;
	while ( time ( NULL ) < end_time )//time()取得当前时间
	{
    
    
		if ( pthread_mutex_lock ( &mutex ) !=0 )
		{
    
    
			perror ( "pthread_mutex_lock" );
			
			pthread_exit((void *)-1);
			
		}
		else
			printf ( "pthread1 lock\n" );

		
		for ( i=0;i<2;i++ )
		{
    
    
			sleep (1 );
			lock_var++;
			printf("pthread1 lock_var=%d\n",lock_var);
		}

		
		if ( pthread_mutex_unlock ( &mutex ) !=0 )
		{
    
    
			perror ( "pthread_mutex_unlock" );
		}
		else
			printf ( "pthread1 unlock\n" );
		sleep ( 1 );
	}
}

void pthread2 ( void *arg )
{
    
    
	
	int ret;
	int i;
	while ( time ( NULL ) < end_time )
	{
    
        
	     //*
	      if((ret= pthread_mutex_lock ( &mutex ))!=0) //阻塞
	      	{
    
    
	           perror("can't get lock\n");
		    	pthread_exit((void *)-1);
	      	}
	        
	      // */
	       /*
		ret=pthread_mutex_trylock ( &mutex );//非阻塞
		if ( ret==EBUSY )
			printf ( "pthread2:the variable is locked by pthread1\n" );
		//*/
		else if(ret==0)
		{
    
    		
			printf ( "pthread2 got lock\n");
			
			for ( i=0;i<2;i++ )
			{
    
    
				sleep (1);
				lock_var++;
				printf("pthread2 lock_var=%d\n",lock_var);	
				
			}
			
			if ( pthread_mutex_unlock ( &mutex ) !=0 )
			{
    
    
				perror ( "pthread_mutex_unlock" );
			}
			else
				printf ( "pthread2 unlock\n" );
		}
	sleep (1 );
	}
}

Example of semaphore mutex lock

//用信号量实现三个线程的互斥操作,且它们的执行顺序是线程1-》2--》3--》1--》2--》3.。。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sys/ipc.h>
#include <semaphore.h>
int lock_var;
time_t end_time;
sem_t sem1,sem2,sem3;

void pthread1(void *arg);
void pthread2(void *arg);
void pthread3(void *arg);


int main(int argc, char *argv[])
{
    
    
	pthread_t id1,id2,id3;
	pthread_t mon_th_id;
	int ret;
	end_time = time(NULL)+30;
	ret=sem_init(&sem1,0,1);
	ret=sem_init(&sem2,0,0);
	ret=sem_init(&sem3,0,0);
	if(ret!=0)
	{
    
    
		perror("sem_init");
	}
	ret=pthread_create(&id1,NULL,(void *)pthread1, NULL);
	if(ret!=0)
		perror("pthread cread1");
	ret=pthread_create(&id2,NULL,(void *)pthread2, NULL);
	if(ret!=0)
		perror("pthread cread2");

	ret=pthread_create(&id3,NULL,(void *)pthread3, NULL);
	if(ret!=0)
		perror("pthread cread2");
	
	pthread_join(id1,NULL);
	pthread_join(id2,NULL);
	pthread_join(id3,NULL);
	exit(0);
}

void pthread1(void *arg)
{
    
    
	int i;
	while(time(NULL) < end_time){
    
    
		sem_wait(&sem1);
		for(i=0;i<2;i++){
    
    
			sleep(1);
			lock_var++;
			printf("pthread1----lock_var=%d\n",lock_var);
		}
		printf("pthread1:lock_var=%d\n",lock_var);
		sem_post(&sem2);
		sleep(1);
	}
}

void pthread2(void *arg)
{
    
    
	int nolock=0;
	int ret;
	while(time(NULL) < end_time){
    
    
	sem_wait(&sem2);
	printf("pthread2:pthread2 got lock;lock_var=%d\n",lock_var);
	sem_post(&sem3);
	sleep(3);
	}
}

void pthread3(void *arg)
{
    
    
	int nolock=0;
	int ret;
	while(time(NULL) < end_time){
    
    
	sem_wait(&sem3);
	printf("pthread3:pthread3 got lock;lock_var=%d\n",lock_var);
	sem_post(&sem1);
	sleep(3);
	}
}

Guess you like

Origin blog.csdn.net/hhltaishuai/article/details/107394546