题目要求
在任务一的基础上进一步,如果我们不想 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 信号量 |
函数 | 说明 |
int pthread_mutex_init (pthread_mutex_t *mutex, pthread_mutexattr_t *attr) int pthread_mutex_destroy(pthread_mutex_t *mutex); |
pthread_mutex_t A = PTHREAD_MUTEX_INITIALIZER;
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;
}