linux下利用互斥实现线程访问共享资源含源文件.docx
《linux下利用互斥实现线程访问共享资源含源文件.docx》由会员分享,可在线阅读,更多相关《linux下利用互斥实现线程访问共享资源含源文件.docx(30页珍藏版)》请在冰豆网上搜索。
![linux下利用互斥实现线程访问共享资源含源文件.docx](https://file1.bdocx.com/fileroot1/2022-11/25/00563182-502f-4883-93a0-e4679a1cbdab/00563182-502f-4883-93a0-e4679a1cbdab1.gif)
linux下利用互斥实现线程访问共享资源含源文件
“计算机操作系统”课程设计大作业
一、实验题目:
linux下利用互斥实现线程访问共享资源
二、实验目的:
掌握线程创建和终止,加深对线程和进程概念的理解,会用同步与互斥方法实现线程之间的通信。
三、实验内容
事先了解操作系统中经典的生产者-消费者问题,安装linux虚拟机(可以用virtualbox或者vmware软件)。
在linux下创建三个生产者线程(P1,P2,P3)和一个消费者线程(C1),生产者和消费者线程共享一个长度为2KB的环型公共缓冲区,生产者向缓冲区写入消息,消费者从缓冲区中取走消息显示到屏幕。
只要缓冲区未满,生产者可将消息送入缓冲区;只要缓冲区未空,消费者可从缓冲区取走一个消息。
每个消息具下列结构格式:
消息长度(1个字节),消息内容(n个字节)。
每个生产者每隔2秒生产一个消息加入缓冲区,并把消息产生时间和内容记录在一个文本文件中。
P1每次生产的数据为26个大写字母,P2每次生产的数据为26个小写字母,P3每次生产的数据为10个阿拉伯数字。
消费者C1每隔3秒读取缓冲区中的一个消息并将消息内容显示到屏幕上。
用两种方法(不采线程用互斥和采用线程互斥技术)编写上述功能的程序,对比两种程序运行结果有何区别?
不采线程用互斥时存在什么问题?
备注:
编程中用到的函数
创建线程函数:
pthread_create
互斥锁初始化:
pthread_mutex_init
互斥锁加锁:
pthread_mutex_lock
互斥锁解锁:
pthread_mutex_unlock
四、实验要求:
每人完成一份大作业实验报告。
报告分设计思想、数据定义、处理流程、源程序、运行结果截图、设计体会等部分。
1)给出数据定义和详细说明;
2)给出实现思想和设计流程;
3)调试完成源程序;
4)屏幕观察运行结果;
5)总结自己的设计体会;
编程语言及操作系统平台不限。
五、提交内容
本大作业每个人必须单独完成。
最后需提交的内容包括:
源程序(关键代码需要注释说明)、可运行程序、算法思路及流程图、心得体会。
大作业必须以WORD附件的形式提交。
大作业严禁抄袭。
发现抄袭一律以不及格论。
大作业内容要完整,一定要有算法思路、流程图、心得体会、运行输出信息截屏等内容,如果只提交源代码则大作业成绩记为不合格。
2016-10-20
linux下利用互斥实现线程访问共享资源
一、原理的理解
生产者-消费者问题是一个经典的线程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。
在同一个线程地址空间内执行的两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
多个生产/消费者在有界缓冲上操作。
它利用N个字节的共享内存作为有界循环缓冲区,利用写一字符模拟放一个产品,利用读一字符模拟消费一个产品。
当缓冲区空时消费者应阻塞睡眠,而当缓冲区满时生产者应当阻塞睡眠。
一旦缓冲区中有空单元,生产者线程就向空单元中入写字符,并报告写的内容和位置。
一旦缓冲区中有未读过的字符,消费者线程就从该单元中读出字符,并报告读取位置。
生产者不能向同一单元中连续写两次以上相同的字符,消费者也不能从同一单元中连续读两次以上相同的字符。
二、完成步骤
1、思路分析
本作业是完善课件上的线程综合实例的练习生产者-消费者问题,重构这个程序的框架,完成性能分析,使之进一步理解掌握Linux下线程的同步、通信以及互斥和多线程的安全问题。
一般情况下,解决互斥方法常用信号量和互斥锁,即semaphore和mutex,而解决这个问题,多采用一个类似资源槽的结构,每个槽位标示了指向资源的指针以及该槽位的状态,生产者和消费者互斥查询资源槽,判断是否有产品或者有空位可以生产,然后根据指针进行相应的操作。
同时,为了告诉生产者或者消费者资源槽的情况,还要有一个消息传送机制,无论是管道还是线程通信。
然而,本次试验有几个特殊的要求:
A、循环缓冲。
B、除了stderr,stdout等外,只用小于2个的互斥锁、
C、放弃资源槽分配机制,采用额外的数据结构。
D、生产者一直持续生产,形成生产消费的良性循环。
首先,使用一个互斥锁,意味着资源槽机制就不能使用了。
因为资源槽虽以用一个互斥锁完成,但是需要有额外的通信,如果使用管道通信,则管道也必须是互斥,这就不满足1个互斥锁的要求。
其次,要求生产者一直生产,这就否定了另外一种方法:
消费者、生产者的位置均平等,消费者消费的时候生产者不能生产,生产者生产的时候消费者不能消费。
因此,就需要采用A要求,也就是循环链表的形式。
为了保证互斥要求,需要定义一个数据结构,这个数据结构包含两个指针,一个读一个写,同时有一个资源数目量,告诉生产者和消费者是否可以生产或者消费。
由于该数据结构很小,因而可以对此结构互斥访问。
同时,对于每组数据,都有一个标志位,表示此组数据是否被占用,生产者和消费者均可以先占用此位置然后完成相应的操作。
当消费者互斥访问此结构时,首先判断是否有数据可以取,如果没有,直接等待,若有数据可取,先更改标志位占用此数据,并将资源数目-1。
然后交出互斥,把数据拷贝到自己缓冲区内,清空数据。
当生产者访问时,首先判断有没有空位可以生产,如果没有,直接等待,若有数据可以生产,先判断该位是否被占用,如果没被占用,则占用此位置进行生产。
生产完成后,将占用位改为未占用,同时将资源数目+1。
这个过程可以如图所示:
2、重要函数和数据结构
(1)数据结构
#defineN5//生产者的数目
#defineN215//消费者数目
#defineM20//缓冲数目
#definedebug0//调试模式
#definenowait1//是否添加额外等待
pthread_mutex_tmutex;//互斥信号量
intprod_id=0;//生产者id
intproc_id=0;//消费者id
//成功以及失败次数计数
intSucc[N+N2];
intFail[N+N2];
//用于生产的填充数据
chardt[30]="aaaaaaaaaabbbbbbbbbbcccccccccc";
inttoexit=0;//退出标记
//共用数据区
structdata_struc
{
intOccupied;//该位置是否被占用无论生产还是消费
chard[1024];//数据
structdata_struc*nx;//下一个指针
};
//互斥量
structmtx
{
structdata_struc*rd_p;
structdata_struc*wr_p;
intcnt;//产品数量
};
structmtx*mymutex;
(2)函数说明
voidprintinfo();//调试函数,打印公用数据区的内容和状态
voidCreate_Empty_DS();//初始化循环链表
void*buy();//消费者
void*sell();//生产者
void*Recount();//数据统计,同时控制程序自动退出
3、程序流程图
A、主函数
B、统计线程
C、生产者线程
D、消费者线程
三、实验数据
1、程序运行截图
虚拟机:
VMwareWorkstation7.0,win7;硬件:
i3,2GDDR1333;编译:
gccproduct.c–pg–lpthread;报告生成:
gprof–b。
运行时截图:
CPU占用情况(无额外等待):
2、原始数据
由于程序要求使用gprof进行分析,而在机器配置较好的情况下,使用gprof可能分析不出每个函数执行时间,甚至连函数都分析不全,因而在实际代码中添加了一些空循环来增加cpu占用。
为了更便于观察,首先假设如下场景:
消费者、生产者在执行各自动作前,均usleep
(1),同时,消费者在成功消费之后,也会usleep(3)来为其他消费者让位。
同时,也将测试没有任何等待的数据。
程序内有一计时线程,每个一秒会显示一次生产消费情况,当60秒后程序自动退出,从而保存数据已被分析。
生产者数量
1
消费者数量
1
缓冲长度
20
额外等待
有
CPU占用
<0.3%
函数分析情况
无法分析到消费者、生产者线程
程序运行情况
生产者:
#1成功次数:
12243失败次数:
12213
消费者:
#1成功次数:
12223失败次数:
0
生产者数量
1
消费者数量
1
缓冲长度
20
额外等待
无
CPU占用
>97%
函数分析情况
%cumulativeselfselftotal
timesecondssecondscallsTs/callTs/callname
54.592.082.08buy
45.413.811.73sell
0.003.810.0010.000.00Create_Empty_DS
Callgraph
granularity:
eachsamplehitcovers4byte(s)for0.26%of3.81seconds
index%timeselfchildrencalledname
[1]54.62.080.00buy[1]
-----------------------------------------------
[2]45.41.730.00sell[2]
-----------------------------------------------
0.000.001/1main[8]
[3]0.00.000.001Create_Empty_DS[3]
-----------------------------------------------
Indexbyfunctionname
[3]Create_Empty_DS[1]buy[2]sell
程序运行情况
生产者:
#1成功次数:
21260失败次数:
1146117485
消费者:
#1成功次数:
21240失败次数:
1151177763
生产者数量
1
消费者数量
5
缓冲长度
20
额外等待
有
CPU占用
<0.3%
函数分析情况
无法分析到消费者、生产者线程
程序运行情况
生产者:
#1成功次数:
24829失败次数:
0
消费者:
#1成功次数:
4900失败次数:
15102
消费者:
#2成功次数:
5261失败次数:
14386
…..
消费者:
#5成功次数:
5069失败次数:
14752
生产者数量
1
消费者数量
5
缓冲长度
20
额外等待
无
CPU占用
>97%
函数分析情况
%cumulativeselfselftotal
timesecondssecondscallsTs/callTs/callname
85.292.902.90buy
14.713.400.50sell
0.003.400.0010.000.00Create_Empty_DS
Callgraph
granularity:
eachsamplehitcovers4byte(s)for0.29%of3.40seconds
index%timeselfchildrencalledname
[1]85.32.900.00buy[1]
-----------------------------------------------
[2]14.70.500.00sell[2]
-----------------------------------------------
0.000.001/1main[8]
[3]0.00.000.001Create_Empty_DS[3]
-----------------------------------------------
Indexbyfunctionname
[3]Create_Empty_DS[1]buy[2]sell
程序运行情况
生产者:
#1成功次数:
10800失败次数:
362944304
消费者:
#1成功次数:
1980失败次数:
368988095
…
消费者:
#5成功次数:
2560失败次数:
391801113
生产者数量
3
消费者数量
10
缓冲长度
20
额外等待
有
CPU占用
约4%
函数分析情况
%cumulativeselfselftotal
timesecondssecondscallsTs/callTs/callname
94.081.591.59sell
5.921.690.10buy
0.001.690.0010.000.00Create_Empty_DS
Callgraph
granularity:
eachsamplehitcovers4byte(s)for0.59%of1.69seconds
index%timeselfchildrencalledname
[1]94.11.590.00sell[1]
-----------------------------------------------
[2]5.90.100.00buy[2]
-----------------------------------------------
0.000.001/1main[8]
[3]0.00.000.001Create_Empty_DS[3]
-----------------------------------------------
Indexbyfunctionname
[3]Create_Empty_DS[2]buy[1]sell
程序运行情况
生产者:
#1成功次数:
161677失败次数:
0
生产者:
#2成功次数:
161412失败次数:
0
生产者:
#3成功次数:
161535失败次数:
0
消费者:
#1成功次数:
44264失败次数:
75030
消费者:
#2成功次数:
47878失败次数:
67808
消费者:
#3成功次数:
47805失败次数:
67967
……
消费者:
#10成功次数:
45942失败次数:
71664
生产者数量
3
消费者数量
10
缓冲长度
20
额外等待
无
CPU占用
>97%
函数分析情况
%cumulativeselfselftotal
timesecondssecondscallsTs/callTs/callname
77.282.962.96buy
22.723.830.87sell
0.003.830.0010.000.00Create_Empty_DS
Callgraph
granularity:
eachsamplehitcovers4byte(s)for0.26%of3.83seconds
index%timeselfchildrencalledname
[1]77.32.960.00buy[1]
-----------------------------------------------
[2]22.70.870.00sell[2]
-----------------------------------------------
0.000.001/1main[8]
[3]0.00.000.001Create_Empty_DS[3]
-----------------------------------------------
Indexbyfunctionname
[3]Create_Empty_DS[1]buy[2]sell
程序运行情况
生产者:
#1成功次数:
4640失败次数:
174184091
生产者:
#2成功次数:
4000失败次数:
179724333
生产者:
#3成功次数:
4120失败次数:
170018676
消费者:
#1成功次数:
1280失败次数:
182205853
消费者:
#2成功次数:
1340失败次数:
173044281
…..
消费者:
#9成功次数:
1020失败次数:
166877134
消费者:
#10成功次数:
1380失败次数:
164803475
生产者数量
5
消费者数量
20
缓冲长度
40
额外等待
有
CPU占用
约9%
函数分析情况
%cumulativeselfselftotal
timesecondssecondscallsTs/callTs/callname
96.374.254.25sell
3.634.410.16buy
0.004.410.0010.000.00Create_Empty_DS
Callgraph
granularity:
eachsamplehitcovers4byte(s)for0.23%of4.41seconds
index%timeselfchildrencalledname
[1]96.44.250.00sell[1]
-----------------------------------------------
[2]3.60.160.00buy[2]
-----------------------------------------------
0.000.001/1main[8]
[3]0.00.000.001Create_Empty_DS[3]
-----------------------------------------------
Indexbyfunctionname
[3]Create_Empty_DS[2]buy[1]sell
程序运行情况
生产者:
#1成功次数:
139689失败次数:
0
生产者:
#2成功次数:
139235失败次数:
0
….
生产者:
#5成功次数:
137801失败次数:
0
消费者:
#1成功次数:
25922失败次数:
96488
消费者:
#2成功次数:
39009失败次数:
70402
消费者:
#3成功次数:
39645失败次数:
69154
…..
消费者:
#20成功次数:
33775失败次数:
80811
生产者数量
5
消费者数量
20
缓冲长度
40
额外等待
无
CPU占用
>97%
函数分析情况
%cumulativeselfselftotal
timesecondssecondscallsTs/callTs/callname
80.292.812.81buy
19.713.500.69sell
0.003.500.0010.000.00Create_Empty_DS
Callgraph
granularity:
eachsamplehitcovers4byte(s)for0.29%of3.50seconds
index%timeselfchildrencalledname
[1]80.32.810.00buy[1]
-----------------------------------------------
[2]19.70.690.00sell[2]
-----------------------------------------------
0.000.001/1main[8]
[3]0.00.000.001Create_Empty_DS[3]
-----------------------------------------------
Indexbyfunctionname
[3]Create_Empty_DS[1]buy[2]sell
程序运行情况
生产者:
#1成功次数:
4120失败次数:
81703999
….
生产者:
#5成功次数:
4200失败次数:
91874644
消费者:
#1成功次数:
1080失败次数:
83483253
消费者:
#2成功次数:
1240失败次数:
85970149
消费者:
#3成功次数:
1360失败次数:
106265813
消费者:
#4成功次数:
960失败次数:
82522392
消费者:
#5成功次数:
1360失败次数:
93462020
消费者:
#6成功次数:
1160失败次数:
91337608
消费者:
#7成功次数:
1520失败次数:
102954859
消费者:
#8成功次数:
1080失败次数:
91363902
消费者:
#9成功次数:
760失败次数:
105319175
消费者:
#10成功次数:
1320失败次数:
102144117
消费者:
#11成功次数:
720失败次数:
90933552
消费者:
#12成功次数:
1120失败次数:
90537228
消费者:
#13成功次数:
920失败次数:
90670465
消费者:
#14成功次数:
840失败次数:
109153419
消费者:
#15成功次数:
1320失败次数:
91949204
消费者:
#16成功次数:
960失败次数:
80094023
消费者:
#17成功次数:
1120失败次数:
81866777
消费者:
#18成功次数:
1000失败次数: