多线程打印 - 互斥量的使用
迪丽瓦拉
2024-02-25 13:24:24
0

题目要求

在任务一的基础上进一步,如果我们不想 A 和 B 的行交替出现,即无论该程序运行多少次都是先连续打印三行 A 再连续打印三行 B,或者反之,连续打印三行 B 再连续打印三行 A也可以,该如何实现?(提示,使用 mutex)

相关知识:

l 临界资源:首先谈一下临界资源的概念:某些资源来说,其在同一时间只能被一段机器指令序列所占用。这些一次只能被一段指令序列所占用的资源就是所谓的临界资源。典型的临界资源比如物理上的打印机,或是存在硬盘或内存中被多个进程/线程所共享的一些变量和数据等。这类资源如果不被看成临界资源加以保护,那么很有可能因为访问冲突造成数据错乱的问题。

l 临界区:对于临界资源的访问,必须是互斥进行。也就是当临界资源被一个指令序列占用时,另一个需要访问相同临界资源的指令序列就不能被执行。我们知道这里所说的指令序列在现实中就都是作为进程/线程的一部分被OS调度执行的,指令序列不能执行的实际意思就是我们所说的其所在的进程/线程会被阻塞,直到其所申请的临界资源被释放。而程序内访问临界资源的代码序列被称为临界区。

l 互斥:是指同时只允许一个访问者对临界资源进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

l 同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

Linux上对线程互斥和同步的支持方法。

互斥

同步

进程

System V信号量

POSIX 信号量

线程锁共享

System V信号量(常用于进程的同步,还不清楚是否可以用于线程)

POSIX 信号量

线程

pthread_mutex_t

POSIX 信号量

pthread_cond_t

POSIX 信号量

  1. 线程库互斥量的使用

函数

说明

int  pthread_mutex_init

(pthread_mutex_t  *mutex,

pthread_mutexattr_t *attr)  

int pthread_mutex_destroy(pthread_mutex_t *mutex);

  1. 静态初始化可以通过PTHREAD_MUTEX_INITIALIZER宏

pthread_mutex_t A = PTHREAD_MUTEX_INITIALIZER;

  1. 动态初始化可以通过pthread_mutex_init函数进行,一般在通过pthread_mutex_init初始化的锁,在不需要时应调用pthread_mutex_destroy销毁。

attr:  互斥锁属性  //  NULL表示缺省属性

int  pthread_mutex_lock(pthread_mutex_t *mutex)

通过pthread_mutex_lock来获得锁

注意: 如果想获得的锁已经被别的线程获取了,此时pthread_mutex_lock将引起调用者阻塞

int  pthread_mutex_unlock(pthread_mutex_t *mutex)

通过pthread_mutex_unlock来释放获得的锁

审核要求:

1. 提交全部程序代码,代码思路规范清晰,命名规范。

2. 运行能直接输出所要求的结果。

#include 
#include 	
pthread_mutex_t mtx;
void *funa(void *arg)
{	if(0!=pthread_mutex_lock(&mtx)){perror("perror_mutex_lock");exit(0);}int i;for(i=0;i<3;i++){sleep(1);printf("AAAAAAAAAA\n");}if(0!=pthread_mutex_unlock(&mtx)){perror("perror_mutex_lock");exit(0);}pthread_exit(NULL);
}void *funb(void *arg)
{if(0!=pthread_mutex_lock(&mtx)){perror("perror_mutex_lock");exit(0);}int i;for(i=0;i<3;i++){sleep(1);printf("BBBBBBBBBB\n");}if(0!=pthread_mutex_unlock(&mtx)){perror("perror_mutex_lock");exit(0);}pthread_exit(NULL);
}int main()
{	pthread_t ta,tb;if(0!=pthread_mutex_init(&mtx,NULL)){perror("pthread_mutex_init");exit(0);}if(0!=pthread_create(&ta,NULL,funa,NULL)){perror("pthread error!");exit(0);}if(0!=pthread_create(&tb,NULL,funb,NULL)){perror("pthread error!");exit(0);}if(0!=pthread_join(ta,NULL)){perror("join error\n");exit(0);}if(0!=pthread_join(tb,NULL)){perror("join error\n");exit(0);}if(0!=pthread_mutex_destroy(&mtx)){perror("pthread_mutex_destroy");exit(0);}return 0;
}

相关内容