Linux程序设计-7.线程同步

7. 线程同步

线程同步:协调步骤,顺序执行

7.1 互斥量

7.1.1 销毁并初始化一个锁pthread_mutex_init()

包含头文件:

  • #include <pthread.h>

函数原型:

  • int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
参数说明
restrict约束该块内存区域对应的数据,只能通过后面的变量进行访问和修改
mutex互斥量(锁)
attr互斥量的属性,可以不考虑,NULL

7.1.2 给共享资源加锁pthread_mutex_lock()

包含头文件:

  • #include <pthread.h>

函数原型:

  • int pthread_mutex_lock(pthread_mutex_t *mutex);

函数说明:

  • 如果当前为锁,成功,该线程加锁
  • 如果当前已锁,阻塞等待
参数说明
mutex互斥量
return成功:0
失败:errno,立即返回

7.1.3 pthread_mutex_trylock()

包含头文件:

  • #include <pthread.h>

函数原型:

  • int pthread_mutex_trylock(pthread_mutex_t *mutex);

函数说明:

  • 如果当前为锁,成功,该线程加锁
  • 如果当前已锁,立即返回
参数说明
mutex互斥量
return成功:0
失败:errno,立即返回
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

pthread_mutex_t mutex;

void *thr(void *arg)
{
	while(1)
	{
		pthread_mutex_trylock(&mutex);
		printf("hello world\n");
		sleep(30);
		pthread_mutex_unlock(&mutex);
	}
	return NULL;
}

int main()
{
	pthread_mutex_init(&mutex,NULL);
	pthread_t tid;
	pthread_create(&tid, NULL, thr, NULL);
	sleep(1);
	while(1)
	{
		int ret = pthread_mutex_trylock(&mutex);
		if(ret > 0)
		{
			printf("ret = %d, sttmsg = %s\n", ret, strerror(ret));
			sleep(1);
		}
	}
	return 0;
}

运行结果:
在这里插入图片描述

7.1.4 给共享资源解锁pthread_mutex_unlock()

包含头文件:

  • #include <pthread.h>

函数原型:

  • int pthread_mutex_unlock(pthread_mutex_t *mutex);

函数说明:

  • 如果当前为锁,成功,该线程解锁
参数说明
mutex互斥量
return成功:0
失败:errno

7.1.5 销毁一个锁pthread_mutex_destroy()

包含头文件:

  • #include <pthread.h>

函数原型:

  • int pthread_mutex_destroy(pthread_mutex_t *mutex);
参数说明
mutex传入的锁
return成功:0
失败:errno

7.1.6 常量初始化

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

未添加锁打印:

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

void *thr1(void *arg)
{
	while(1)
	{
		printf("hello");
		sleep(rand()%3);
		printf("world\n");
		sleep(rand()%3);
	}
}

void *thr2(void *arg)
{
	while(1)
	{
		printf("HELLO");
		sleep(rand()%3);
		printf("WORLD\n");
		sleep(rand()%3);
	}
}

int main()
{
	srand((unsigned)time(NULL));
	pthread_t tid[2];
	pthread_create(&tid[0], NULL, thr1, NULL);
	pthread_create(&tid[1], NULL, thr2, NULL);
	pthread_join(tid[0], NULL);
	pthread_join(tid[1], NULL);
	return 0;
}

运行结果:
在这里插入图片描述
添加锁打印:

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *thr1(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		printf("hello");
		sleep(rand()%3);
		printf("world\n");
		pthread_mutex_unlock(&mutex);
		sleep(rand()%3);
	}
}

void *thr2(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		printf("HELLO");
		sleep(rand()%3);
		printf("WORLD\n");
		pthread_mutex_unlock(&mutex);
		sleep(rand()%3);
	}
}

int main()
{
	srand((unsigned)time(NULL));
	pthread_t tid[2];
	pthread_create(&tid[0], NULL, thr1, NULL);
	pthread_create(&tid[1], NULL, thr2, NULL);
	pthread_join(tid[0], NULL);
	pthread_join(tid[1], NULL);
	return 0;
}

运行结果:
在这里插入图片描述

7.2 读写锁

特点:读共享、写独占、写优先级高
读写锁仍然是一把锁,有不同的状态

  • 未加锁
  • 读锁
  • 写锁

7.2.1 初始化读写锁pthread_rwlock_init()

函数原型:

  • int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);

初始化常量pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

7.2.2 销毁读写锁pthread_rwlock_destroy()

函数原型:

  • int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

7.2.3 加读锁

函数原型:

  • int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
  • int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

7.2.4 加写锁

函数原型:

  • int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

7.2.5 释放锁pthread_rwlock_unlock()

函数原型:

  • int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

读写示例:

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

pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

int begin_num = 1000;

void *thr_write(void* arg)
{
	while(1)
	{
		pthread_rwlock_wrlock(&rwlock);
		printf("write thread:%lu %d\n", pthread_self(), ++begin_num);
		sleep(1);
		pthread_rwlock_unlock(&rwlock);
		sleep(2);
	}
	return NULL;
}

void *thr_read(void* arg)
{
	while(1)
	{
		pthread_rwlock_rdlock(&rwlock);
		printf("read thread:%lu %d\n", pthread_self(), begin_num);
		sleep(1);
		pthread_rwlock_unlock(&rwlock);
		sleep(1);
	}
	return NULL;
}

int main()
{
	int n = 8, i = 0;
	pthread_t tid[8];
	for (i = 0;i < 5;i++)
	{
		pthread_create(&tid[i], NULL, thr_read, NULL);
	}
	for (;i < 8;++i)
	{
		pthread_create(&tid[i], NULL ,thr_write, NULL);
	}
	for(i = 0;i < 8;i++)
	{
		pthread_join(tid[i], NULL);
	}
	return 0;
}

运行结果:
在这里插入图片描述

7.3 条件变量

条件变量:可以引起阻塞,并非锁

7.3.1 初始化条件

函数原型:

  • int pthread_cond_init(pthread_cond_t *cond);

初始化变量pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

7.3.2 销毁条件变量

函数原型:

  • int pthread_cond_destroy(pthread_cond_t *cond);

7.3.3 等待条件

函数原型:

  • int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
  • int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);

函数说明:

  • pthread_cond_timedwait:超时等待
  • pthread_cond_wait:阻塞等待
  • 条件变量不是锁需要和互斥量组合使用
  • 先释放mutex
  • 阻塞在cond

7.3.4 唤醒线程

7.3.4.1 唤醒至少一个阻塞在cond上线程

函数原型:

  • int pthread_cond_signal(pthread_cond_t *cond);
7.2.4.2 唤醒阻塞在条件cond上的全部线程

函数原型:

  • int pthread_cond_broadcast(pthread_cond_t *cond);

示例代码(生产者、消费者模型):

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int begin_num = 1000;

typedef struct _ProdInfo
{
	int num;
	struct _prodInfo *next;
}ProdInfo;

ProdInfo *Head = NULL;

void *thr_producer(void *arg)
{
	while(1)
	{
		ProdInfo *prod = malloc(sizeof(ProdInfo));
		prod->num = begin_num++;
		printf("%s-self=%lu-%d\n", "producer", pthread_self(), prod->num);
		pthread_mutex_lock(&mutex);
		prod->next = Head;
		Head = prod;
		pthread_mutex_unlock(&mutex);
		pthread_cond_signal(&cond);
		sleep(1);
	}
	return NULL;
}

void *thr_customer(void *arg)
{
	ProdInfo * prod = NULL;
	while(1)
	{
		pthread_mutex_lock(&mutex);
		while(Head == NULL)
		{
			pthread_cond_wait(&cond, &mutex); // 再此之前必须先加锁
		}
		prod = Head;
		Head = Head->next;
		printf("%s-self=%lu-%d\n", "customer", pthread_self(), prod->num);
		pthread_mutex_unlock(&mutex);
		free(prod);
		prod = NULL;
		sleep(2);
	}
	return NULL;
}

int main()
{
	pthread_t tid[3];
	pthread_create(&tid[0], NULL, thr_producer, NULL);
	pthread_create(&tid[1], NULL, thr_customer, NULL);
	pthread_create(&tid[2], NULL, thr_customer, NULL);
	pthread_join(tid[0], NULL);
	pthread_join(tid[1], NULL);
	pthread_join(tid[2], NULL);
	pthread_cond_destroy(&cond);
	pthread_mutex_destroy(&mutex);
	return 0;
}

运行结果:
在这里插入图片描述

7.4 信号量

7.4.1 初始化信号量sem_init()

包含头文件:

  • #include <semaphore.h>

函数原型:

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

函数说明:

  • sem:信号量
  • pshared:取0用于线程间;非0(一般为1)用于进程间
  • value:信号量初始值

7.4.2 销毁信号量sem_destroy()

包含头文件:

  • #include <semaphore.h>

函数原型:

  • int sem_destroy(sem_t *sem);

7.4.3 释放信号量sem_post()

包含头文件:

  • #include <semaphore.h>

函数原型:

  • int sem_post(sem_t *sem);

函数说明:

释放成功:value++

7.4.4 申请信号量

包含头文件:

  • #include <semaphore.h>

函数原型:

  • int sem_wait(sem_t *sem);
  • int sem_trywait(sem_t *sem);
  • int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

函数说明:

申请成功,value--

生产者消费者模型:

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

#define _SEM_CNT_ 5

sem_t blank, xfull;
int queue[_SEM_CNT_];
int begin_num = 100;

void *thr_producer(void *arg)
{
	int i = 0;
	while(1)
	{
		sem_wait(&blank);
		printf("producer:self=%lu:%d\n", pthread_self(),begin_num);
		queue[(i++)%_SEM_CNT_] = begin_num++;
		sem_post(&xfull);
		sleep(rand()%3);
	}
	return NULL;
}

void *thr_customer(void *arg)
{
	int i = 0, num;
	while(1)
	{
		sem_wait(&xfull);
		num = queue[(i++) % _SEM_CNT_];
		printf("customer:self=%lu:%d\n", pthread_self(),num);
		sem_post(&blank);
		sleep(rand()%3);
	}
	return NULL;
}

int main()
{
	sem_init(&blank, 0, _SEM_CNT_);
	sem_init(&xfull, 0, 0);
	pthread_t tid[2];
	pthread_create(&tid[0], NULL, thr_producer, NULL);
	pthread_create(&tid[1], NULL, thr_customer, NULL);
	pthread_join(tid[0], NULL);
	pthread_join(tid[1], NULL);
	sem_destroy(&blank);
	sem_destroy(&xfull);
	return 0;
}

运行结果:
在这里插入图片描述

7.5 文件锁

struct flock {
	...
	short l_type;    /* 锁类型: F_RDLCK, F_WRLCK, F_UNLCK */
	short l_whence;  /* 位置: SEEK_SET, SEEK_CUR, SEEK_END */
	off_t l_start;   /* 锁的起始位置 */
	off_t l_len;     /* 锁定的字节数 */
	pid_t l_pid;     /* 由F_GETLK和F_OFD_GETLK设置 */
	...
           };
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
	int fd = open(argv[1], O_RDWR | O_CREAT, 0666);
	if(fd < 0)
	{
		perror("open err");
		return -1;
	}
	struct flock lk;
	lk.l_type = F_WRLCK;
	lk.l_whence = SEEK_SET;
	lk.l_start = 0;
	lk.l_len = 0;
	if(fcntl(fd, F_SETLK, &lk) < 0)
	{
		perror("get lock err");
		exit(-2);
	}
	while(1)
	{
		printf("***\n");
		sleep(1);
	}
	return 0;
}
  • 31
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT灰猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值