locks, condition variables, semaphores

thread synchronization

mutex

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<pthread.h>
#include<time.h>

//定义一把锁
pthread_mutex_t mutex;

void *mythread1(void* args)
{
    
    
    while(1)
    {
    
    
        //加锁
        pthread_mutex_lock(&mutex);

        printf("hello");
        sleep(rand()%3);
        printf(" world\n");

        //解锁
        pthread_mutex_unlock(&mutex);
        sleep(rand()%3);
    }
    pthread_exit(NULL);
}

void *mythread2(void* args)
{
    
    
    while(1)
    {
    
    
        //加锁
        pthread_mutex_lock(&mutex);

        printf("HELLO");
        sleep(rand()%3);
        printf(" WORLD\n");

        //解锁
        pthread_mutex_unlock(&mutex);
        sleep(rand()%3);
    }
    pthread_exit(NULL);
}

int main()
{
    
    
    int ret;
    pthread_t thread1;
    pthread_t thread2;

    //随机数种子
    srand(time(NULL));

    //互斥锁初始化
    pthread_mutex_init(&mutex,NULL);

    ret=pthread_create(&thread1,NULL,mythread1,NULL);
    if(ret!=0)
    {
    
    
        printf("pthread_create error,[%s]\n",strerror(ret));
        return -1;
    }

    ret=pthread_create(&thread2,NULL,mythread1,NULL);
    if(ret!=0)
    {
    
    
        printf("pthread_create error,[%s]\n",strerror(ret));
        return -1;
    }

    //等待线程结束
    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);

    //释放互斥锁
    pthread_mutex_destroy(&mutex);
    return 0;

}

Locks must be added to all threads that operate shared resources, otherwise the synchronization effect cannot be achieved

deadlock

Deadlock is not a method of use provided by Linux to users, but a phenomenon caused by improper use of mutex locks by users

The first

lock yourself

void *mythread1(void* args)
{
    
    
    while(1)
    {
    
    
        //加锁
        pthread_mutex_lock(&mutex);
        pthread_mutex_lock(&mutex);

        printf("hello");
        sleep(rand()%3);
        printf(" world\n");

        //解锁
        pthread_mutex_unlock(&mutex);
        sleep(rand()%3);
    }
    pthread_exit(NULL);
}

the second

Thread A owns A lock and requests to obtain B lock; thread B owns B lock and requests to obtain A lock, which causes thread A and thread B to not release their own locks, but also wants to obtain each other's locks, resulting in a deadlock

image-20211125153226385

solve:

  • Let threads access shared resources in a certain order
  • When accessing other locks, you need to unlock your own lock first
  • Call pthread_mutex_trylock, if the lock is unsuccessful, it will return immediately

read-write lock

Read-write locks are also called shared-exclusive locks. When a reader-writer lock is locked in read mode, it is locked in shared mode; when it is locked in write mode, it is locked in exclusive mode

Write Exclusive, Read Shared

It is suitable for situations where the number of data structure reads is much greater than that of writes

  • When the read-write lock is "locked in write mode", all threads that lock the lock will be blocked before unlocking
  • When the read-write lock is "locked in read mode", if the thread locks it in read mode, it will succeed; if the thread locks in write mode, it will block
  • When the read-write lock is "locked in read mode", there are both threads trying to lock in write mode and threads trying to lock in read mode. Then the read-write lock blocks subsequent read-mode lock requests. Write mode locks are satisfied first. Read locks and write locks are blocked in parallel, and write locks have high priority
//定义一把读写锁
pthread_rwlock_t rwlock;

//初始化读写锁
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);
//rwlock-读写锁
//attr-读写锁属性,传NULL为默认属性

//销毁读写锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);        

//加读锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);              

//尝试加读锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

//加写锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

//尝试加写锁
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

//解锁
int pthread_rwlock_unlock(&pthread_rwlock_t *rwlock);

condition variable

The condition itself is not a lock, but it can also cause a thread to block. Usually used in conjunction with a mutex. Provide a meeting place for multiple threads

  • Protect shared data with mutexes
  • Use condition variables to block threads, wait for a condition to occur, and unblock when the condition is met

two actions

  • The condition is not met, blocking the thread
  • When the condition is met, notify the blocked thread to unblock and start working

related functions

pthread_cond_t  cond;
//定义一个条件变量

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
//函数描述:初始化条件变量
//cond: 条件变量
//attr: 条件变量属性, 通常传NULL
//成功返回0, 失败返回错误号

int pthread_cond_destroy(pthread_cond_t *cond);
//销毁条件变量
//函数参数: 条件变量
//返回值: 成功返回0, 失败返回错误号

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
//条件不满足, 引起线程阻塞并解锁;条件满足, 解除线程阻塞, 并加锁
//cond: 条件变量
//mutex: 互斥锁变量
//函数返回值: 成功返回0, 失败返回错误号

int pthread_cond_signal(pthread_cond_t *cond);
//唤醒至少一个阻塞在该条件变量上的线程
//函数参数: 条件变量
//函数返回值: 成功返回0, 失败返回错误号

amount of signal

It is equivalent to multiple locks, which can be understood as an enhanced version of the mutex lock

related functions

//定义信号量 
sem_t sem;


int sem_init(sem_t *sem, int pshared, unsigned int value);	
//初始化信号量
//sem: 信号量变量
//pshared: 0表示线程同步, 1表示进程同步
//value: 最多有几个线程操作共享数据
//成功返回0, 失败返回-1, 并设置errno值

int sem_wait(sem_t *sem);
//调用该函数一次, 相当于sem--, 当sem为0的时候, 引起阻塞
//函数参数: 信号量变量
//成功返回0, 失败返回-1, 并设置errno值

int sem_post(sem_t *sem);
//调用一次, 相当于sem++
//函数参数: 信号量变量
//成功返回0, 失败返回-1, 并设置errno值

int sem_trywait(sem_t *sem);
//尝试加锁, 若失败直接返回, 不阻塞
//函数参数: 信号量变量
//函数返回值: 成功返回0, 失败返回-1, 并设置errno值

int sem_destroy(sem_t *sem);
//销毁信号量
//函数参数: 信号量变量
//函数返回值: 成功返回0, 失败返回-1, 并设置errno值

Guess you like

Origin blog.csdn.net/blll0/article/details/121539433