操作系统 实验 五 线程间的互斥与同步

合集下载

进程的同步与互斥实验报告

进程的同步与互斥实验报告

进程的同步与互斥实验报告1.实验目的进程(线程)的同步与互斥是操作系统中非常重要的概念,本实验旨在通过实际操作,加深对这些概念的理解和掌握。

通过编写多个进程(线程),并在其间进行同步与互斥操作,验证同步与互斥的实际效果。

2.实验环境本实验在Linux系统下进行,使用C/C++语言编程。

3.实验内容3.1同步在实验中,我们编写了两个进程A和B,这两个进程需要按照特定的顺序执行。

为了实现同步,我们使用信号量机制来确保进程A和B按照正确的顺序执行。

3.2互斥在实验中,我们编写了多个进程C和D,这些进程需要同时对一个共享资源进行访问。

为了实现互斥,我们使用互斥锁机制来确保同一时刻只有一个进程访问共享资源。

4.实验过程4.1同步实验编写进程A和进程B的代码,使用信号量机制实现同步。

进程A先运行,然后通过信号量唤醒进程B,进程B再开始执行。

通过观察进程的运行顺序,验证同步机制是否起作用。

4.2互斥实验编写进程C和进程D的代码,使用互斥锁机制实现互斥。

进程C和进程D同时对一个共享资源进行访问,通过互斥锁来确保同一时刻只有一个进程访问共享资源。

观察进程的输出结果,验证互斥机制是否起作用。

5.实验结果5.1同步实验结果进程A开始执行进程A执行完毕进程B开始执行进程B执行完毕5.2互斥实验结果进程C开始执行进程C访问共享资源进程C执行完毕进程D开始执行进程D访问共享资源进程D执行完毕6.实验分析通过上述结果可以看出,同步实验中进程A和进程B按照正确的顺序执行,证明了同步机制的有效性。

互斥实验中进程C和进程D能够正确地交替访问共享资源,证明了互斥机制的有效性。

7.实验总结通过本次实验,我深刻理解了进程(线程)的同步与互斥,并通过实际操作加深了对这些概念的理解。

同步和互斥是操作系统中非常重要的概念,对于应对资源竞争和提高程序性能具有重要意义。

在实际开发中,我们应该合理使用同步和互斥机制,以确保程序的正确性和并发执行的效率。

操作系统同步和互斥

操作系统同步和互斥

操作系统同步和互斥操作系统中的进程之间的关系只有两种:同步与互斥。

下面由店铺为大家整理了操作系统的同步和互斥的相关知识,希望对大家有帮助!操作系统同步和互斥1.进程同步进程同步也是进程之间直接的制约关系,是为完成某种任务而建立的两个或多个线程,这个线程需要在某些位置上协调他们的工作次序而等待、传递信息所产生的制约关系。

进程间的直接制约关系来源于他们之间的合作。

比如说进程A需要从缓冲区读取进程B产生的信息,当缓冲区为空时,进程B因为读取不到信息而被阻塞。

而当进程A产生信息放入缓冲区时,进程B才会被唤醒。

2.进程互斥进程互斥是进程之间的间接制约关系。

当一个进程进入临界区使用临界资源时,另一个进程必须等待。

只有当使用临界资源的进程退出临界区后,这个进程才会解除阻塞状态。

比如进程B需要访问打印机,但此时进程A占有了打印机,进程B会被阻塞,直到进程A释放了打印机资源,进程B才可以继续执行。

扩展:临界资源在操作系统中,进程是占有资源的最小单位(线程可以访问其所在进程内的所有资源,但线程本身并不占有资源或仅仅占有一点必须资源)。

但对于某些资源来说,其在同一时间只能被一个进程所占用。

这些一次只能被一个进程所占用的资源就是所谓的临界资源。

典型的临界资源比如物理上的打印机,或是存在硬盘或内存中被多个进程所共享的一些变量和数据等(如果这类资源不被看成临界资源加以保护,那么很有可能造成丢数据的问题)。

对于临界资源的访问,必须是互诉进行。

也就是当临界资源被占用时,另一个申请临界资源的进程会被阻塞,直到其所申请的临界资源被释放。

而进程内访问临界资源的代码被成为临界区。

对于临界区的访问过程分为四个部分:1.进入区:查看临界区是否可访问,如果可以访问,则转到步骤二,否则进程会被阻塞2.临界区:在临界区做操作3.退出区:清除临界区被占用的标志4.剩余区:进程与临界区不相关部分的代码临界资源使用规则:忙则等待、优先等待、空闲让进、让权等待(在临界区的进程,不能在临界区内长时间处于事件等待,必须在一定时间退出临界区)。

互斥与同步

互斥与同步

互斥与同步互斥与同步是计算机科学中两个重要的概念,它们是多线程编程中必须掌握的知识点。

本文将介绍互斥与同步的概念、原理、实现方式以及应用场景。

一、互斥1.1 概念互斥是指在多线程并发执行时,对于共享资源的访问需要保证线程之间的排他性,即在任意时刻只有一个线程能够访问共享资源。

1.2 原理互斥的实现基于锁机制,即在访问共享资源前获取锁,在使用完毕后释放锁。

这样可以保证在任意时刻只有一个线程能够获得锁,从而避免了多个线程同时访问共享资源造成的数据竞争问题。

1.3 实现方式常见的实现方式包括:(1)临界区:将对共享资源的访问限制在一个代码块内,在进入临界区前获取锁,在离开临界区后释放锁。

(2)信号量:通过计数器来控制同时进入临界区的线程数量,当计数器为0时表示当前没有进入临界区的线程,当计数器大于0时表示当前有进入临界区的线程。

(3)互斥量:是一种特殊的信号量,只能被一个线程获取,其他线程需要等待该线程释放互斥量后才能获取。

1.4 应用场景互斥常用于对共享资源的访问控制,例如多个线程同时访问同一个文件、数据库或网络连接等。

二、同步2.1 概念同步是指在多线程并发执行时,保证线程之间的协调和顺序性,使得程序按照预期的顺序执行。

2.2 原理同步的实现基于信号机制,即在某个条件满足时通知其他线程进行操作。

例如,在生产者-消费者模型中,当生产者生产了数据后需要通知消费者进行消费。

2.3 实现方式常见的实现方式包括:(1)条件变量:通过等待和唤醒操作来实现对某个条件的等待和通知。

(2)事件对象:是一种特殊的条件变量,可以通过事件对象来设置和清除事件状态,并在事件状态发生改变时通知其他线程进行操作。

(3)屏障:是一种同步原语,在多个线程到达屏障点时会被阻塞,直到所有线程都到达后才会继续执行。

2.4 应用场景同步常用于对线程之间的协调和顺序性控制,例如在多个线程之间进行任务分配、消息传递等。

三、互斥与同步的关系互斥和同步是两个相互依存的概念。

线程并发实验报告

线程并发实验报告

一、实验目的1. 理解线程的概念和并发编程的基本原理。

2. 掌握线程的创建、同步和通信方法。

3. 通过实验加深对线程并发编程的理解,提高编程能力。

二、实验环境1. 操作系统:Windows 102. 开发工具:Visual Studio 20193. 编程语言:C++三、实验内容本次实验主要涉及以下内容:1. 线程的创建与销毁2. 线程的同步与互斥3. 线程的通信4. 线程池的使用四、实验步骤1. 线程的创建与销毁(1)创建线程:使用C++11标准中的`std::thread`类创建线程。

```cpp#include <iostream>#include <thread>void threadFunction() {std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl;}int main() {std::thread t1(threadFunction);std::thread t2(threadFunction);t1.join(); // 等待线程t1结束t2.join(); // 等待线程t2结束return 0;}```(2)销毁线程:线程会在任务执行完毕后自动销毁,无需手动销毁。

2. 线程的同步与互斥(1)互斥锁:使用`std::mutex`类实现线程间的互斥。

```cpp#include <iostream>#include <thread>#include <mutex>std::mutex mtx;void threadFunction() {mtx.lock();std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl;mtx.unlock();}int main() {std::thread t1(threadFunction);t1.join();t2.join();return 0;}```(2)条件变量:使用`std::condition_variable`类实现线程间的条件同步。

线程的互斥实验报告总结

线程的互斥实验报告总结

线程的互斥实验报告总结
本次实验是关于线程互斥的,旨在通过使用互斥锁和信号量等机制,让学生能够更好地理解并掌握线程的互斥操作。

在本次实验中,我们首先学习了互斥锁的概念和使用方法。

互斥
锁是一种最常用的线程同步机制,用来保证多个线程之间的互斥操作。

通过使用互斥锁,我们可以避免两个或多个线程同时访问共享资源而
导致数据异常的问题。

实验中,我们对比了有互斥锁与没有互斥锁对
共享变量的访问结果,明显地看到了在没有互斥锁的情况下,数据会
发生异常。

除了互斥锁,我们还学习了信号量的概念和使用方法。

信号量是
一种用于控制访问共享资源的标志,在多线程程序中广泛应用。

使用
信号量可以保证多个线程间共享资源的安全性,并可以避免资源竞争
和死锁的发生。

在实验中,我们还利用信号量实现了线程的同步和互
斥操作。

通过本次实验,我深感互斥锁和信号量在多线程程序中的重要性。

在多线程编程中,不仅要考虑到线程之间的并发问题,也需要关注到
线程之间的同步和互斥操作。

只有将线程同步和互斥机制运用到多线
程编程中,才能真正保证多线程程序的安全性和正确性。

综上所述,本次实验对于我来说是非常有意义的。

通过学习互斥
锁和信号量等线程同步机制,我对于多线程编程的思想和技术又有了
更深刻的理解和认识。

我相信,在今后的学习和工作中,所学到的知识一定会给我带来更多的帮助和启示。

线程同步和互斥概念

线程同步和互斥概念

线程同步和互斥概念在多线程编程中,线程同步和互斥是非常重要的概念。

线程同步指的是多个线程在执行过程中的协调和合作,以达到共同的目标。

而线程互斥则是指多个线程在访问共享资源时的互相排斥,以保证数据的一致性和正确性。

一、线程同步线程同步是指多个线程之间的协调和合作,以达到共同的目标。

在多线程编程中,线程同步可以通过各种机制来实现,例如锁、信号量、事件等。

1. 锁机制锁机制是最常见的线程同步机制之一。

锁机制可以保证在同一时间只有一个线程可以访问共享资源,其他线程需要等待锁的释放才能访问。

常见的锁有互斥锁、读写锁等。

例如,在一个多线程环境下,多个线程需要访问同一个全局变量,为了保证数据的一致性和正确性,可以使用互斥锁来实现线程同步。

2. 信号量机制信号量机制是另一种常见的线程同步机制。

信号量可以用来控制并发线程的数量,以达到线程同步的目的。

常见的信号量有二元信号量和计数信号量。

例如,在一个多线程环境下,多个线程需要访问同一个共享资源,为了保证数据的一致性和正确性,可以使用计数信号量来控制并发线程的数量。

3. 事件机制事件机制是一种高级的线程同步机制,可以用来实现线程之间的通信和协调。

事件机制通常包括事件对象、事件等待和事件通知等。

例如,在一个多线程环境下,多个线程需要协调完成一项任务,可以使用事件机制来实现线程同步。

二、线程互斥线程互斥是指多个线程在访问共享资源时的互相排斥,以保证数据的一致性和正确性。

在多线程编程中,线程互斥可以通过各种机制来实现,例如锁、信号量、事件等。

1. 锁机制锁机制可以用来实现线程互斥。

在同一时间只有一个线程可以获得锁,其他线程需要等待锁的释放才能访问共享资源。

例如,在一个多线程环境下,多个线程需要访问同一个全局变量,为了保证数据的一致性和正确性,可以使用互斥锁来实现线程互斥。

2. 信号量机制信号量机制也可以用来实现线程互斥。

通过设置信号量的初始值为1,可以保证只有一个线程可以访问共享资源。

操作系统实验进程同步与互斥

操作系统实验进程同步与互斥

操作系统实验进程同步与互斥操作系统实验进程同步与互斥实验目的1.掌握进程同步和互斥原理,理解生产者-消费者模型;2.学习Windows2000/xp中的多线程并发执行机制;3.学习使用Windows SDK解决读者-写者问题。

试验内容1依据生产者-消费者模型,在Windows 2000/xp环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥,分析、熟悉生产者消费者问题仿真的原理和实现技术。

(见附件2)试验内容2参考实验内容1和附件2伪码,编程解决读者-写者问题的程序。

(具体要求和读写者问题原始伪码内容见附件1)相关知识Windows 2000/XP的线程控制CreateThread完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。

ExitThread用于结束当前线程。

SuspendThread可挂起指定的线程。

ResumeThread可激活指定线程,它的对应操作是递减指定线程的挂起计数,当挂起计数减为0时,线程恢复执行。

Windows 2000/XP的进程互斥和同步在Windows 2000/XP中提供了临界区、互斥对象、信号量对象同步对象和相应的系统调用,用于进程和线程同步。

临界区对象(Critical Section)只能用于在同一进程内使用的临界区,同一进程内各线程对它的访问是互斥进行的。

相关API包括:InitializeCriticalSection对临界区对象进行初始化;EnterCriticalSection等待占用临界区的使用权,得到使用权时返回;TryEnterCriticalSection非等待方式申请临界区的使用权;申请失败时,返回0;LeaveCriticalSection释放临界区的使用权;DeleteCriticalSection释放与临界区对象相关的所有系统资源。

互斥对象(Mutex)互斥对象相当于互斥信号量,在一个时刻只能被一个线程使用。

线程同步和互斥的区别

线程同步和互斥的区别

线程同步和互斥的区别
1. 互斥是指某⼀资源同时只允许⼀个访问者对其进⾏访问,具有唯⼀性和排它性。

但互斥⽆法限制访问者对资源的访问顺序,即访问是
⽆序的。

2. 同步是指在互斥的基础上(⼤多数情况),通过其它机制实现访问者对资源的有序访问。

3. 同步其实已经实现了互斥,所以同步是⼀种更为复杂的互斥。

4. 互斥是⼀种特殊的同步。

所谓互斥,就是不同线程通过竞争进⼊临界区(共享的数据和硬件资源),为了防⽌访问冲突,在有限的时间内只允许其中之⼀独占性的使⽤共享资源。

如不允许同时写
同步关系则是多个线程彼此合作,通过⼀定的逻辑关系来共同完成⼀个任务。

⼀般来说,同步关系中往往包含互斥,同时对临界区的资源会按照某种逻辑顺序进⾏访问。

如先⽣产后使⽤
总的来说,两者的区别就是:
互斥是通过竞争对资源的独占使⽤,彼此之间不需要知道对⽅的存在,执⾏顺序是⼀个乱序。

同步是协调多个相互关联线程合作完成任务,彼此之间知道对⽅存在,执⾏顺序往往是有序的。

lock与unlock⽅法,替换synchronized,这就是互斥锁的体现。

消费者⽣产者模式就是同步锁的体现。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验五线程间的互斥与同步
实验学时:2学时
实验类型:验证、设计型
一、实验目的
理解POSIX线程(Pthread)互斥锁和POSIX信号量机制,学习它们的使用方法;编写程序,实现多个POSIX线程的同步控制。

二,实验内容
创建4个POSIX线程。

其中2个线程(A和B)分别从2个数据文件(data1.txt和data2.txt)读取10个整数. 线程A和B把从文件中读取的逐一整数放入一个缓冲池. 缓冲池由n个缓冲区构成(n=5,并可以方便地调整为其他值),每个缓冲区可以存放一个整数。

另外2个线程,C和D,各从缓冲池读取10数据。

线程C、D每读出2个数据,分别求出它们的和或乘积,并打印输出。

提示:在创建4个线程当中,A和B是生产者,负责从文件读取数据到公共的缓冲区,C和D是消费者,从缓冲区读取数据然后作不同的计算(加和乘运算)。

使用互斥锁和信号量控制这些线程的同步。

不限制线程C和D从缓冲区得到的数据来自哪个文件。

在开始设计和实现之前,务必认真阅读课本6.8.4节和第6章后面的编程项目——生产者-消费者问题。

三,实验要求
按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。

四,实验设计
1,功能设计
根据实验要求,主程序需要创建四个线程,两个线程负责从文件读取数据到缓冲区,两个线程负责将缓冲区的数据做数学运算。

由于同一个进程中的各个线程共享资源,可以用一个二维数组的全局变量作为公共缓冲区,同时还需要一个整形全局变量size用来做数组的索引。

读线程的运行函数打开不同的文件并从中读取数据到二维数组中,每次写入数组后size加一。

运算线程从二维数组中读数并做运算,每次读数之前size减一。

本题的关键在于如何使用信号量保证进程的同步与互斥。

在运算线程从缓冲区读取之前缓冲区里必须有数,即任意时刻运算操作的执行次数必须小于等于读取操作的执行次数。

同时应该保证两个读线程和两个运算线程两两互斥。

由于以上分析,使用了四个信号量sem1,sem2,sem3和sem4。

sem1保证线程1和线程2互斥,sem2保证线程3和线程4互斥,sem3保证线程3和线程4互斥,sem4保证线程4和线程1互斥。

即这四个信号量使四个线程循环进行,从而保证了运行结果的正确性。

源代码及注释:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM 200
int stack[NUM][2]; //公共缓冲区
int size=0; //初始化数组索引
sem_t sem1,sem2,sem3,sem4; //定义四个信号量
void read1(void){ //线程运行函数,负责从文件读取数据FILE *fp=fopen("data0.txt","r"); //以只读方式打开文件data1
while(!feof(fp)){
sem_wait(&sem1); //减少信号量sem1
if(!fscanf(fp,"%d %d",&stack[size][0],&stack[size][1]))return;
size++; //读两个数到公共缓冲区
sem_post(&sem2); //增加信号量sem2
}
fclose(fp); //关闭文件
}
void read2(void){ //线程运行函数,负责从文件读取数据FILE *fp=fopen("data1.txt","r"); //以只读方式打开文件data2
while(!feof(fp)){
sem_wait(&sem2); //减少信号量sem2
if(!fscanf(fp,"%d %d",&stack[size][0],&stack[size][1]))return;
size++; //读两个数到公共缓冲区
sem_post(&sem3); //增加信号量sem3
}
fclose(fp);
}
void plus1(void){ //线程运行函数,负责加运算
while(1){
sem_wait(&sem3); //减少信号量sem3
if(size==0){return;}
size--;
printf("Plus:%d+%d=%d\n",stack[size][0],stack[size][1],stack[size][0]+stack[size][1] ); //从公共缓冲区取数并进行加运算
sem_post(&sem4); //增加信号量sem3
}
}
void multi2(void){ //线程运行函数,负责乘运算
while(1){
sem_wait(&sem4); //减少信号量sem4
if(size==0){return;}
size--;
printf("Multiply:%d*%d=%d\n",stack[size][0],stack[size][1],stack[size][0]*stack[size ][1]); //从公共缓冲区取数并进行乘运算
sem_post(&sem1); //增加信号量sem3
}
}
int main(void){
pthread_t t1,t2,t3,t4; //定义线程标识符
sem_init(&sem1,0,1); //初始化信号量
sem_init(&sem2,0,0);
sem_init(&sem3,0,0);
sem_init(&sem4,0,0);
pthread_create(&t1,NULL,(void *)read1,NULL); //创建线程,绑定线程运行函数pthread_create(&t2,NULL,(void *)read2,NULL);
pthread_create(&t3,NULL,(void *)plus1,NULL);
pthread_create(&t4,NULL,(void *)multi2,NULL);
pthread_join(t1,NULL); //等待线程运行结束
}
2,数据结构
信号量(semaphore):数据类型为结构 sem_t,本质上是一个长整型的数。

公共缓冲区(stack):采用2维数组的方式实现(stack[NUM][2])。

数组中的两列分别存储两个文件中的数据。

该2维数组还有一个索引:size,指向2维数组的顶部。

五,实验测试结果及分析
实验截图:
如图所示,加线程和乘线程从缓冲区读取数据,进行运算,并将运算结果输出。

六,收获及体会
在本次实验中,我学习了UNIX 类操作系统信号量机制,掌握了编写Linux 环境下利用信号量实现进程控制的方法及相关系统调用的使用方法。

在编译的时候也遇到了一些问题,在读取时data0和data1时出现过读取的错误,在使用信号量对线程控制时出现了一些错误,运算总是出现顺序问题。

通过测试与调试,我找出了错误原因,并修改了程序中的信号量设置方式,严格控制各个线程的执行顺序,终于解决了问题。

在这个过程中我加深了对于信号量操作的理解与认识。

七,参考资料《2011秋季实验指导》。

相关文档
最新文档