当前位置:   article > 正文

Linux线程——线程同步_linux之线程管理头歌

linux之线程管理头歌

线程同步指的是当一个线程在对某个临界资源进行操作时,其他线程都不可以对这个资源进行操作,直到该线程完成操作,其他线程才能操作,也就是协同步调,让线程按预定的先后次序进行运行。线程同步的方法有四种:互斥锁、信号量、条件变量、读写锁。

1.互斥锁

头文件及函数声明:

#include <pthread.h>
/*
mutex是锁,
attr是锁的属性,一般用不上,传个NULL默认属性就可以
*/
int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_mutex_destroy(pthread_mutex_t *mutex);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

示例代码
以下代码在多线程并发中已经做过分析。我们这里直接进行修改。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<pthread.h>

pthread_mutex_t mutex;//定义锁
int g = 0;

void* pthread_fun(void* arg)
{
    for(int i = 0; i < 1000; i++)
    {
        pthread_mutex_lock(&mutex);//上锁
        g++;
        printf("g = %d\n",g);
        pthread_mutex_unlock(&mutex);//解锁
    }
    pthread_exit(NULL);
}

int main()
{
    
    pthread_mutex_init(&mutex, NULL);//初始化锁

    pthread_t id[5];
    for(int i = 0; i < 5; i++)
    {
        pthread_create(&id[i],NULL,pthread_fun,NULL);
    }

    for(int j = 0; j < 5; j++)
    {
        char* s = NULL;
        pthread_join(id[j],(void**)&s);
    }
    
    pthread_mutex_destroy(&mutex);//销毁锁
    exit(0);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

运行结果最后输出都是5000,不会再出现低于5000的情况。

2 信号量

头文件及函数声明:

#include <semaphore.h>
/*
sem:信号对象。
pshared:指明信号量的类型。不为0时此信号量在进程间共享,为0时只能为当前进程的所有线程共享。
value:指定信号量值的大小。
*/
int sem_init(sem_t *sem, int pshared, unsigned int value);

int sem_wait(sem_t *sem);//原子操作,P操作,将信号值减1

int sem_post(sem_t *sem);//原子操作,V操作,将信号值加1

int sem_destroy(sem_t *sem);//销毁信号量
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

示例代码:函数线程完成将用户输入的数据存储到文件中

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<pthread.h>
#include<semaphore.h>
#include<fcntl.h>

sem_t sem1;
sem_t sem2;
char buff[128] = {0};

void* pthread_fun(void* arg)
{
    int fd = open("sem.txt",O_WRONLY|O_CREAT,0664);
    assert(fd != -1);
    while(1)
    {
        sem_wait(&sem2);
        if(strncmp(buff,"end",3) == 0)
        {
            break;
        }
        write(fd,buff,strlen(buff));
        memset(buff,0,128);
        sem_post(&sem1);
    }
    sem_destroy(&sem1);
    sem_destroy(&sem2);
    pthread_exit(NULL);
}

int main()
{
    sem_init(&sem1,0,1);
    sem_init(&sem2,0,0);
    pthread_t id;
    int res = pthread_create(&id,NULL,pthread_fun,NULL);
    assert(res == 0);

    while(1)
    {
        printf("please input data:\n");

        sem_wait(&sem1);
        fgets(buff,128,stdin);
        buff[strlen(buff)-1] = '\0';
        sem_post(&sem2);

        if(strncmp(buff, "end", 3) == 0)
        {
            break;
        }
    }
    char* s = NULL;
    pthread_join(id,(void**)s);
    
    exit(0);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

3.条件变量

条件变量提供了一种线程间的通知机制:当某个共享数据达到某个值的时候,唤醒等待这个共享数据的线程。
头文件及函数声明:

#include <pthread.h>
/*
cond:
attr:
*/
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

int pthread_cond_signal(pthread_cond_t *cond); //唤醒单个线程

int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒所有等待的线程

int pthread_cond_destroy(pthread_cond_t *cond);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

pthread_mutex_t mutex;
pthread_cond_t cond;
void * fun1( void * arg)
{
	char* s = ( char*)arg;
	while( 1 )
	{
		//阻塞,被唤醒
		pthread_mutex_lock(&mutex);
		pthread_cond_wait(&cond,&mutex);
		pthread_mutex_unlock(&mutex);

		printf("fun1 read:%s\n",s);

		if (strncmp(s,"end",3) == 0 )
		{
			break;
		}
	}
}

void * fun2( void * arg)
{
	char* s = ( char*)arg;
	while( 1 )
	{
		//阻塞,被唤醒
		pthread_mutex_lock(&mutex);
		pthread_cond_wait(&cond,&mutex);
		pthread_mutex_unlock(&mutex);

		printf("fun2 read:%s\n",s);

		if ( strncmp(s,"end",3) == 0 )
		{
			break;
		}
	}
}

int main()
{
	pthread_t id[2];
	char buff[128] = {0};

	pthread_cond_init(&cond,NULL);
	pthread_mutex_init(&mutex,NULL);
	pthread_create(&id[0],NULL,fun1,( void*)buff);
	pthread_create(&id[1],NULL,fun2,( void*)buff);

	while( 1 )
	{
		fgets(buff,128,stdin);

		if ( strncmp(buff,"end",3) == 0 )
		{
			pthread_mutex_lock(&mutex);
			pthread_cond_broadcast(&cond);
			pthread_mutex_unlock(&mutex);

			break;
		}
		else
		{
			pthread_mutex_lock(&mutex);
			pthread_cond_signal(&cond);
			pthread_mutex_unlock(&mutex);
		}
	}

	pthread_join(id[0],NULL);
	pthread_join(id[1],NULL);
	exit(0);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

4.读写锁

头文件及函数声明:

#include <pthread.h>
/*
rwlock:指向读写锁的指针
attr:读写锁属性,一般传入NULL,使用默认属性
每一个函数执行成功就返回0,否则就返回一个错误码
*/
int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr);

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//都锁定

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

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解锁读写锁

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//释放读写锁
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/336648
推荐阅读
相关标签
  

闽ICP备14008679号