导航:首页 > 操作系统 > linux线程共享内存

linux线程共享内存

发布时间:2024-04-02 21:39:19

1. linux共享内存的分配

进程通过调用shmget(Shared Memory GET,获取共享内存)来分配一个共享内存块。
该函数的第一个参数是一个用来标识共享内存块的键值。彼此无关的进程可以通过指定同一个键以获取对同一个共享内存块的访问。不幸的是,其它程序也可能挑选了同样的特定值作为自己分配共享内存的键值,从而产生冲突。用特殊常量IPC_PRIVATE作为键值可以保证系统建立一个全新的共享内存块。
该函数的第二个参数指定了所申请的内存块的大小。因为这些内存块是以页面为单位进行分配的,实际分配的内存块大小将被扩大到页面大小的整数倍。
第三个参数是一组标志,通过特定常量的按位或操作来shmget。这些特定常量包括:
IPC_CREAT:这个标志表示应创建一个新的共享内存块。通过指定这个标志,我们可以创建一个具有指定键值的新共享内存块。
IPC_EXCL:这个标志只能与 IPC_CREAT 同时使用。当指定这个标志的时候,如果已有一个具有这个键值的共享内存块存在,则shmget会调用失败。也就是说,这个标志将使线程获得一个“独有”的共享内存块。如果没有指定这个标志而系统中存在一个具有相同键值的共享内存块,shmget会返回这个已经建立的共享内存块,而不是重新创建一个。
模式标志:这个值由9个位组成,分别表示属主、属组和其它用户对该内存块的访问权限。其中表示执行权限的位将被忽略。指明访问权限的一个简单办法是利用<sys/stat.h>中指定,并且在手册页第二节stat条目中说明了的常量指定。例如,S_IRUSR和S_IWUSR分别指定了该内存块属主的读写权限,而 S_IROTH和S_IWOTH则指定了其它用户的读写权限。 下面例子中shmget函数创建了一个新的共享内存块(当shm_key已被占用时则获取对一个已经存在共享内存块的访问),且只有属主对该内存块具有读写权限,其它用户不可读写。
int segment_id = shmget (shm_key, getpagesize (), IPC_CREAT | S_IRUSR| S_IWUSR ); 如果调用成功,shmget将返回一个共享内存标识符。如果该共享内存块已经存在,系统会检查访问权限,同时会检查该内存块是否被标记为等待摧毁状态。

2. linux里面,进程与线程到底有什么本质的区别

线程:是进程中执行的一条路径,是系统调度的最小单位。

进程:是正在运行的程序,是系统分配资源的最小单位。

线程与进程关系

1.一个进程可以有多个线程,一个线程只能属于一个进程。

2.同一个进程下的所有线程共享该进程下的所有资源。

3.真正在处理机上运行的是线程,不是进程,线程是进程内的一个执行单元,是进程内的可调度实体。

Linux线程与进程区别

进程:

优点:多进程可以同时利用多个CPU,能够同时进行多个操作。

缺点:耗费资源(创建一个进程重新开辟内存空间)。

进程不是越多越好,一般进程个数等于cpu个数。

线程:

优点:共享内存,尤其是进行IO操作(网络、磁盘)的时候(IO操作很少用cpu),可以使用多线程执行并发操作。

缺点:抢占资源。

3. Linux绾跨▼鍜岃繘绋媗inux镄勭嚎绋嫔拰杩涚▼

linuxtop镆ョ湅镄勬槸杩涚▼杩樻槸绾跨▼锛

top锻戒护姣忎竴琛屾樉绀虹殑鏄涓涓杩涚▼锛屽姞涓-H(Threadstoggle)镄勫悗缂鏄剧ず镄勬墠鏄绾跨▼銆

linux绾跨▼鍏变韩鍜岃繘绋嫔唴瀛樼殑鍏崇郴锛

鍖哄埆鍜岃仈绯伙细

1銆佽繘绋嬫槸镫绔嬭繍琛岀殑瀹炰綋锛屾湁镫绔嬬殑璧勬簮鍒嗛厤锛

2銆佸悓涓杩涚▼镄勭嚎绋嬩箣闂村叡浜杩涚▼镄勮祫婧愶绂

3銆佹墍链夌殑杩涚▼镊冲皯链変竴涓镓ц岀嚎绋嬶绂

4銆佺嚎绋嬬殑鍒涘缓鍜屽垏鎹浠d环姣旇繘绋嬬殑灏忥绂绾跨▼闂寸殑阃氢俊鏂规硶锛1銆佸悓涓杩涚▼镄勭嚎绋嬩箣闂撮氢俊镄勬渶绠鍗曞姙娉曞氨鏄浣跨敤鍏ㄥ眬鍙橀噺锛2銆佷笉钖岃繘绋嬬殑绾跨▼涔嬮棿阃氢俊闇瑕侀氲繃涓嬮溃杩涚▼闂寸殑阃氢俊𨱒ュ疄鐜帮绂杩涚▼闂寸殑阃氢俊鏂规硶锛1銆佺¢亾2銆佷俊鍙烽噺3銆佸叡浜鍐呭瓨4銆佹秷鎭阒熷垪5銆佸楁帴瀛

linux镐庝箞鎸囧畾绾跨▼搴掳纻

澶ф傜殑浠嬬粛涓涓婰inux镄勬寚瀹欳PU杩愯岋纴鍖呮嫭杩涚▼鍜岀嚎绋嬨俵inux涓嬬殑top锻戒护鏄鍙浠ユ煡鐪嫔綋鍓岖殑cpu镄勮繍琛岀姸镐侊纴鎸1鍙浠ユ煡鐪嬬郴缁熸湁澶氩皯涓狢PU锛屼互鍙婃疮涓狢PU镄勮繍琛岀姸镐併傚彲鏄濡备綍镆ョ湅绾跨▼镄凛PU锻锛

top-Hppid,pid灏辨槸浣犲綋鍓岖▼搴忕殑杩涚▼鍙凤纴濡傛灉鏄澶氱嚎绋嬬殑璇濓纴鏄鍙浠ユ煡鐪嬭繘绋嫔唴镓链夌嚎绋嬬殑CPU鍜屽唴瀛树娇鐢ㄦ儏鍐点

pstree鍙浠ユ煡鐪嬩富娆$嚎绋嬶纴钖屾牱镄刾stree-ppid銆傚彲浠ユ煡鐪嬭繘绋嬬殑绾跨▼𨱍呭喌銆

taskset杩欎釜鍏跺疄镓嶆槸閲岖偣锛屽彲浠ユ煡鐪嬩互鍙婅剧疆褰揿墠杩涚▼鎴栫嚎绋嬭繍琛岀殑CPU(璁剧疆浜插拰锷)銆

taskset-pcpid,镆ョ湅褰揿墠杩涚▼镄刢pu锛屽綋铹舵湁镄勬椂鍊欎笉鍙鏄涓涓锛宼askset-pccpu_numpid,cpu_num灏辨槸璁剧疆镄刢pu銆傝繖镙风殑璇濆熀链镄勫懡浠ゅ拰镎崭綔鍏跺疄澶у堕兘鐭ラ亾浜嗭纴鎺ヤ笅𨱒ュ氨鏄鍦ㄤ唬镰佷腑瀹屾垚杩欎簺镎崭綔锛屽苟阃氲繃锻戒护铡婚獙璇佷唬镰佺殑鎴愬姛鐜囥傝繘绋嫔埗瀹欳PU杩愯岋细

viewplain#include#include#include#include#include#define__USE_GNU#include#include#includeintmain(intargc,char*argv){//sysconf銮峰彇链夊嚑涓狢PUintnum=sysconf(_SC_NPROCESSORS_CONF);intcreated_thread=0;intmyid;inti;intj=0;//铡熺悊鍏跺疄寰堢亩鍗曪纴灏辨槸阃氲繃cpu_set_t杩涜屼綅涓庢搷浣渃pu_set_tmask;cpu_set_tget;if(argc!=2){printf(usage:./cpunumn);exit(1);}myid=atoi(argv)

;printf(systemhas%iprocessor(s).n,num)

;//鍏堣繘琛屾竻绌猴纴铹跺悗璁剧疆鎺╃爜CPU_ZERO(mask);CPU_SET(myid,mask)

;//璁剧疆杩涚▼镄勪翰鍜屽姏if(sched_setaffinity(0,sizeof(mask),mask)==-1){printf(warning:couldnotsetCPUaffinity,continuing...n);}while(1){CPU_ZERO(get);//銮峰彇褰揿墠杩涚▼镄勪翰鍜屽姏if(sched_getaffinity(0,sizeof(get),get)==-1){printf(warning:coundnotgetcpuaffinity,continuing...n);}for(i=0;inum;i++){if(CPU_ISSET(i,get)){printf(thisprocess%disrunningprocessor:%dn,getpid(),i);}}}return0;}杩涚▼璁剧疆CPU杩愯岋纴鍏跺疄鍙鑳芥槸鍗旷嚎绋嬨傚氱嚎绋嬭惧畾CPU濡备笅锛

viewplain#define_GNU_SOURCE#include#include#include#include#include#includevoid*myfun(void*arg){cpu_set_tmask;cpu_set_tget;charbuf;inti;intj;//钖屾牱镄勫厛铡昏幏鍙朇PU镄勪釜鏁癷ntnum=sysconf(_SC_NPROCESSORS_CONF);printf(systemhas%dprocessor(s)n,num);for(i=0;inum;i++){CPU_ZERO(mask);CPU_SET(i,mask);//杩欎釜鍏跺疄鍜岃剧疆杩涚▼镄勪翰鍜屽姏锘烘湰鏄涓镙风殑if(pthread_setaffinity_np(pthread_self(),sizeof(mask),mask)0){fprintf(stderr,setthreadaffinityfailedn);}CPU_ZERO(get);if(pthread_getaffinity_np(pthread_self(),sizeof(get),get)0){fprintf(stderr,getthreadaffinityfailedn);}for(j=0;jnum;j++){if(CPU_ISSET(j,get)){printf(thread%disrunninginprocessor%dn,(int)pthread_self(),j);}}j=0;while(j++100000000){memset(buf,0,sizeof(buf));}}pthread_exit(NULL);}intmain(intargc,char*argv){pthread_ttid;if(pthread_create(tid,NULL,(void*)myfun,NULL)!=0){fprintf(stderr,threadcreatefailedn);return-1;}pthread_join(tid,NULL);return0;}

linux涓镄勭嚎绋嬫湁鍝鍑犵岖姸镐侊纻

灏辩华锛氱嚎绋嫔垎閰崭简CPU浠ュ栫殑鍏ㄩ儴璧勬簮锛岀瓑寰呰幏寰桟PU璋冨害镓ц岋细绾跨▼銮峰缑CPU锛屾e湪镓ц岄樆濉烇细绾跨▼鐢变簬鍙戠敓I/O鎴栬呭叾浠栫殑镎崭綔瀵艰嚧镞犳硶缁х画镓ц岋纴灏辨斁寮冨勭悊链猴纴杞鍏ョ嚎绋嫔氨缁阒熷垪鎸傝捣锛氱敱浜庣粓绔璇锋眰锛屾搷浣灭郴缁熺殑瑕佹眰绛夊师锲狅纴瀵艰嚧鎸傝捣銆

linux鍐呮牳涓锛屽伐浣滈槦鍒楀拰绾跨▼链変粈涔埚尯鍒锛

workqueue鏄涓绉峛ottomhalf锛屼腑鏂澶勭悊镄勫悗鍗婄▼锛屽己璋幂殑鏄锷ㄦ佺殑姒傚康锛屽嵆work鏄閲岖偣锛岃宷ueue鏄鍏舵°

waitqueue鏄涓绉嶃屼换锷¢槦鍒椼嶏纴鍙浠ユ妸涓浜涜繘绋嬫斁鍦ㄤ笂闱㈢浔鐪犵瓑寰呮煇涓浜嬩欢锛屽己璋冮润镐佸氢竴浜涳纴閲岖偣鍦╭ueue涓婏纴鍗冲畠灏辨槸涓涓犹ueue锛岃繖涓犹ueue濡备綍璋冨害锛屼粈涔堟椂鍊栾皟搴﹀苟涓嶉吨瑕佺瓑寰呴槦鍒楀湪鍐呮牳涓链夊緢澶氱敤阃旓纴灏ゅ叾阃傚悎鐢ㄤ簬涓鏂澶勭悊锛岃繘绋嫔悓姝ュ强瀹氭椂銆傝繖閲屽彧璇达纴杩涚▼缁忓父蹇呴’绛夊緟镆愪簺浜嬩欢镄勫彂鐢熴备緥濡傦纴绛夊緟涓涓纾佺洏镎崭綔镄勭粓姝锛岀瓑寰呴喷鏀剧郴缁熻祫婧愶纴鎴栬呯瓑寰呮椂闂寸粡杩囧浐瀹氱殑闂撮殧銆傜瓑寰呴槦鍒楀疄鐜颁简鍦ㄤ簨浠朵笂镄勬浔浠剁瓑寰咃纴甯屾湜绛夊緟鐗瑰畾浜嬩欢镄勮繘绋嬫妸鏀捐繘钖堥傜殑绛夊緟阒熷垪锛屽苟鏀惧纯鎺у埗𨱒冦傚洜姝ゃ傜瓑寰呴槦鍒楄〃绀轰竴缁勭浔鐪犵殑杩涚▼锛屽綋镆愪竴𨱒′欢涓虹湡镞讹纴鐢卞唴镙稿敜阅掕繘绋嬨傜瓑寰呴槦鍒楃敱寰鐜阈捐〃瀹炵幇锛屽叾鍏幂礌鍖呮嫭鎸囧悜杩涚▼鎻忚堪绗︾殑鎸囬拡銆傛疮涓绛夊緟阒熷垪閮芥湁涓涓绛夊緟阒熷垪澶达纴绛夊緟阒熷垪澶存槸涓涓绫诲瀷涓簑ait_queue_head_t镄勬暟鎹缁撴瀯銆傜瓑寰呴槦鍒楅摼琛ㄧ殑姣忎釜鍏幂礌浠h〃涓涓镌$湢杩涚▼锛岃ヨ繘绋嬬瓑寰呮煇涓浜嬩欢镄勫彂鐢燂纴鎻忚堪绗﹀湴鍧瀛樻斁鍦╰ask瀛楁典腑銆傜劧钥岋纴瑕佸敜阅掔瓑寰呴槦鍒椾腑镓链夌殑杩涚▼链夋椂骞朵笉鏂逛究銆备緥濡傦纴濡傛灉涓や釜鎴栧氢釜杩涚▼鍦ㄧ瓑寰呬簰鏂ヨ块梾镆愪竴涓瑕侀喷鏀剧殑璧勬簮锛屼粎鍞ら啋绛夊緟阒熷垪涓涓涓镓嶆湁镒忎箟銆傝繖涓杩涚▼鍗犳湁璧勬簮锛岃屽叾浠栬繘绋嬬户缁镌$湢鍙浠ョ敤DECLARE_WAIT_QUEUE_HEAD(name)瀹忓畾涔変竴涓鏂扮殑绛夊緟阒熷垪锛岃ュ畯闱欐佸湴澹版槑鍜屽埯濮嫔寲钖崭负name镄勭瓑寰呴槦鍒楀ご鍙橀噺銆俰nit_waitqueue_head()鍑芥暟鐢ㄤ簬鍒濆嫔寲宸插姩镐佸垎閰岖殑waitqueuehead鍙橀噺绛夊緟阒熷垪鍙浠ラ氲繃DECLARE_WAITQUEUE()闱欐佸垱寤猴纴涔熷彲浠ョ敤init_waitqueue_head()锷ㄦ佸垱寤恒傝繘绋嬫斁鍏ョ瓑寰呴槦鍒楀苟璁剧疆鎴愪笉鍙镓ц岀姸镐併傚伐浣滈槦鍒楋纴workqueue锛屽畠鍏佽稿唴镙镐唬镰佹潵璇锋眰鍦ㄥ皢𨱒ユ煇涓镞堕棿璋幂敤涓涓鍑芥暟銆傜敤𨱒ュ勭悊涓嶆槸寰堢揣镐ヤ簨浠剁殑锲炶皟鏂瑰纺澶勭悊鏂规硶.宸ヤ綔阒熷垪镄勪綔鐢ㄥ氨鏄鎶婂伐浣沧帹钖,浜ょ敱涓涓鍐呮牳绾跨▼铡绘墽琛岋纴镟寸洿鎺ョ殑璇村氨鏄鍐欎简涓涓鍑芥暟,钥岀幇鍦ㄤ笉𨱍抽┈涓婃墽琛屽畠锛岄渶瑕佸湪灏嗘潵镆愪釜镞跺埢铡绘墽琛岋纴闾e氨寰楃敤宸ヤ綔阒熷垪鍑嗘病阌欍傚傛灉闇瑕佺敤涓涓鍙浠ラ吨鏂拌皟搴︾殑瀹炰綋𨱒ユ墽琛屼笅鍗婇儴澶勭悊锛屼篃搴旇ヤ娇鐢ㄥ伐浣滈槦鍒椼傛槸鍞涓鑳藉湪杩涚▼涓娄笅鏂囱繍琛岀殑涓嫔崐閮ㄥ疄鐜扮殑链哄埗銆傝繖镒忓懗镌鍦ㄩ渶瑕佽幏寰楀ぇ閲忕殑鍐呭瓨镞躲佸湪闇瑕佽幏鍙栦俊鍙烽噺镞讹纴鍦ㄩ渶瑕佹墽琛岄樆濉炲纺镄処/O镎崭綔镞讹纴閮戒细闱炲父链夌敤銆

4. linux系统下进程通信的6种方式分别是什么它们的区别在什么地方线程通信有几种方式这是很多人的疑问

管道:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

信号量 :信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

消息队列:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

信号 :
信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
共享内存:共享内存就是映射一段能被其他进程所访问的内存,这段共享内由一个进程创建,多个进程都可以访问。共享内存是最快的IPC 方式,
它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,合使用,来实现进程间的同步和通信。

套接字: 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信

管道可以用于shell重定向,也就是命令管道类似grep
命名管道可以实现通信,通过makefifo传递消息
消息队列也可以实现通信,不过相比命名管道有消息过滤的好处
信号其实就是KILL的应用
信号量是对临界共享资源的合理调度
共享内存, 就是字面意思共享的内存

而线程通信方式有:互斥锁,条件变量,读写锁

5. 有人能教下我有关linux里面线程的知识吗

.线程的基本介绍
(1)线程的概述
线程与进程类似,也允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程,同一程序中的所有线程共享同一份全局内存区域,线程之间没有真正意义的等级之分。同一个进程中的线程可以并发执行,如果处理器是多核的话线程也可以并行执行,如果一个线程因为等待I/O操作而阻塞,那么其他线程依然可以继续运行
(2)线程优于进程的方面

argv,environ

主线程栈
线程3的栈
线程2的栈
线程1的栈
共享函数库共享的内存

未初始化的数据段
初始化数据段
文本
.进程间的信息难以共享。由于除去只读代码段外,父子进程并未共享内存,因此必须采用一些进程间通讯,在进程之间交换信息
.调用fork()来创建进程代价相对较高
线程很好的解决了上述俩个问题
.线程之间能够方便,快速的共享信息,只需将数据复制到共享(全局或堆)变量中即可
.创建线程比创建线程通常要快10甚至更多,线程创建之所以快,是因为fork创建进程时所需复制多个属性,而在线程中,这些属性是共享的。
(3)创建线程
启动程序时,产生的进程只有单条线程,我们称之为主线程
#include<pthread.h>
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void*(*start)(void *),void *arg);12

新线程通过调用带有arg的函数开始执行,调用pthread_create()的线程会继续执行该调用之后的语句。
(4)终止线程
可以以如下方式终止线程的运行
.线程调用pthread_exit()
.线程start函数执行return语句并返回指定值
.调用pthread_cancel()取消线程
.任意线程调用了exit(),或者主线程执行了return语句,都会导致进程中的所有线程立即终止
pthread_exit()函数可以终止线程,且其返回值可由另一线程通过调用pthread_join()获得
#include<pthread.h>void pthread_exit(void *retval);12

调用pthread_exit()相当于在线程的start函数中执行return,不同之处在于,pthread_exit()可以在任何地方调用,参数retval指定了线程的返回值
(5)获取线程ID
#include<pthread.h>pthread_t pthread_self(void);12

线程ID在应用程序中主要有如下用途
.不同的pthreads函数利用线程ID来标识要操作目标线程。
.在具体的应用程序中,以特定线程的线程ID作为动态数据结构的标签,这颇有用处,既可用来识别某个数据结构的创建者或属主线程,又可确定随后对该数据结构执行操作的具体线程
函数pthread_equal()可检查俩个线程的ID是否相同
#include<pthread.h>int pthread_equal(pthread_t t1,pthread_t t2);//如果相同返回非0值,否则返回0123

(6)连接已终止的线程
函数pthread_join()等待由thread表识的线程终止
#include<pthread.h>int pthread_join(pthread_t thread,void **retval);//返回0调用成功,否则失败123

如果pthread_join()传入一个之前已然连接过的线程ID,将会导致无法预知的行为,当相同线程ID在参与一次连接后恰好为另一新建线程所重用,再度连接的可能就是这个新线程
若线程未分离,则就应该使用pthread_join()来连接线程,否则会产生僵尸线程
pthrea_join()函数的要点
.线程之间的关系是对等的,所以任意线程都可以调用pthread_join()来连接其他线程
.pthread_join()无法针对任意线程,只能连接单个线程
(6)线程的分离
默认情况下线程都是可连接的,但有时候,我们并不关心线程退出的状态,我们可以调用pthread_detach()并向thread参数传入指定线程的的标识符,将该线程标记为处于分离状态
#include<pthread.h>int pthread_detach(pthread_t thread);//返回0成功,否则失败123

一旦线程处于分离状态,就不能在使用pthread_join()来获取其状态,也无法使其重返可连接状态
(7)在应用程序中如何来选择进程还是线程
.线程之间共享数据很简单,进程间的数据共享需要更多的投入
.创建线程要比创建进程块很多
.多线程编程时,需要确保调用线程安全的函数
.某个线程中的bug可能会危害进程中所有线程
.每个线程都在征用宿主进程中有限的虚拟地址空间
.在多线程应用中,需要小心使用信号
.除了数据,线程还可以共享文件描述符,信号处置,当前工作目录,以及用户ID和组ID
线程的同步
(1)保护共享变量访问:互斥量
线程的主要优势在于能够通过全局变量来共享信息,不过这种共享是有代价的。必须确保多个线程修改同一变量时,不会有其他线程也正在修改此变量,为避免线程更新时共享变量时所出现的问题,必须使用互斥量来确保同时仅有一个线程可以访问某项共享资源
(2)静态分配的互斥锁
互斥锁既可以像静态变量那样分配,也可以在运行时动态分配,互斥量属于pthread_mutex_t类型的变量,在使用之前必须对其初始化。对于静态分配的互斥量而言,可如下例所示,将PTHREAD_MUTEX_INITIALIZER赋给互斥量
pthread_mutex_t = PTHREAD_MUTEX_INITIALIZER;1

1.加锁和解锁互斥量
初始化之后,互斥量处于未锁定状态。函数pthread_mutex_lock()可以锁定某一互斥量
而函数pthread_mutex_unlock()则可以将一个互斥量解锁
#include<pthread.h>int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);//返回0成功,其他失败1234

要锁定互斥量,在调用pthread_mutex_lock()时需要指定互斥量,如果互斥量当前处于未锁定状态,则该调用将会立即返回,如果该互斥量已被其他线程锁定,那么该调用将会阻塞,直至互斥量被解锁
函数pthread_mutex_unlock()将解锁之前已遭调用线程锁定的互斥量
2.互斥量的性能
通常情况下,线程会花费更多的时间去做其他工作,对互斥量的加锁解锁相对要少的多,因此使用互斥量对大部分程序来说性能并无显着的影响
3.互斥量的死锁
当一个线程需要同时访问多个共享资源时,没个资源由不同的互斥索管理。当超过一个线程加锁同一组互斥量时,就有可能发生死锁。如下图所示
线程A
1.pthread_mutex_lock(mutex1);
2.pthread_mutex_lock(mutex2);
线程2
1.pthread_mutex_lock(mutex2);
2.pthread_mutex_lock(mutex1);
每个线程都成功的锁住一个互斥量,接着试图对以为另一线程锁定的互斥量加锁,就会一直等下去
要避免此类死锁问题,最简单的就是定义互斥量的层级关系

6. Linux线程及同步

linux多线程
1.线程概述
线程是一个进程内的基本调度单位,也可以称为轻量级进程。线程是在共享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。因此,大大减少了上下文切换的开销。一个进程可以有多个线程,也就
是有多个线程控制表及堆栈寄存器,但却共享一个用户地址空间。
2.线程实现
线程创建pthread_create()
所需头文件#include
<pthread.h>
函数原型int
pthread_create
((pthread_t
*thread,
pthread_attr_t
*attr,
thread:线程标识符
attr:线程属性设置
start_routine:线程函数的起始地址
arg:传递给start_routine的参数
函数返回值
成功:0
出错:-1
线程退出pthread_exit();
所需头文件#include
<pthread.h>
函数原型void
pthread_exit(void
*retval)
函数传入值retval:pthread_exit()调用者线程的返回值,可由其他函数如pthread_join
来检索获取
等待线程退出并释放资源pthread_join()
所需头文件#include
<pthread.h>
函数原型int
pthread_join
((pthread_t
th,
void
**thread_return))
函数传入值
th:等待线程的标识符
thread_return:用户定义的指针,用来存储被等待线程的返回值(不为NULL时)
函数返回值
成功:0
出错:-1
代码举例
1.
#include<pthread.h>
2.
#include<stdio.h>
3.
#include<errno.h>
4.
5.
/*线程1*/
6.
void
thread1()
7.
{
8.
int
i=0;
9.
10.
while(1)
11.
{
12.
printf(thread1:%d/n,i);
13.
if(i>3)
14.
pthread_exit(0);
15.
i++;
16.
sleep(1);
17.
}
18.
}
19.
20.
/*线程2*/
21.
void
thread2()
22.
{
23.
int
i=0;
24.
25.
while(1)
26.
{
27.
printf(thread2:%d/n,i);
28.
if(i>5)
29.
pthread_exit(0);
30.
i++;
31.
sleep(1);
32.
}
33.
}
34.
35.
int
main()
36.
{
37.
pthread_t
t1,t2;
38.
39.
/*创建线程*/
40.
pthread_create(&t1,NULL,(void
*)thread1,NULL);
41.
pthread_create(&t2,NULL,(void
*)thread2,NULL);
42.
/*等待线程退出*/
43.
pthread_join(t1,NULL);
44.
pthread_join(t2,NULL);
45.
return
0;
46.
}
3同步与互斥
<1>互斥锁
互斥锁的操作主要包括以下几个步骤。

互斥锁初始化:pthread_mutex_init

互斥锁上锁:pthread_mutex_lock

互斥锁判断上锁:pthread_mutex_trylock

互斥锁接锁:pthread_mutex_unlock

消除互斥锁:pthread_mutex_destroy
1.
#include<pthread.h>
2.
#include<stdio.h>
3.
#include<errno.h>
4.
5.
int
i=0;/*共享变量*/
6.
pthread_mutex_t
mutex=PTHREAD_MUTEX_INITIALIZER;/*互斥锁*/
7.
8.
void
thread1()
9.
{
10.
int
ret;
11.
while(1)
12.
{
13.
14.
15.
ret=pthread_mutex_trylock(&mutex);/*判断上锁*/
16.
17.
if(ret!=EBUSY)
18.
{
19.
pthread_mutex_lock(&mutex);/*上锁*/
20.
printf(This
is
thread1:%d/n,i);
21.
i++;
22.
pthread_mutex_unlock(&mutex);/*解锁*/
23.
}
24.
sleep(1);
25.
}
26.
}
27.
28.
void
thread2()
29.
{int
ret;
30.
while(1)
31.
{
32.
33.
ret=pthread_mutex_trylock(&mutex);
34.
if(ret!=EBUSY)
35.
{
36.
pthread_mutex_lock(&mutex);
37.
printf(This
is
thread2:%d/n,i);
38.
i++;
39.
pthread_mutex_unlock(&mutex);
40.
}
41.
sleep(1);
42.
}
43.
}
44.
int
main()
45.
{
46.
pthread_t
t1,t2;
47.
pthread_mutex_init(&mutex,NULL);
48.
pthread_create(&t1,NULL,(void
*)thread1,NULL);
49.
pthread_create(&t2,NULL,(void
*)thread2,NULL);
50.
51.
pthread_join(t1,NULL);
52.
pthread_join(t2,NULL);
53.
54.
pthread_mutex_destroy(&mutex);
55.
return
0;
56.
}
<2>信号量
未进行同步处理的两个线程
1.
#include<pthread.h>
2.
#include<stdio.h>
3.
#include<errno.h>
4.
5.
int
i=0;
6.
void
thread1()
7.
{
8.
9.
while(1)
10.
{
11.
printf(This
is
thread1:%d/n,i);
12.
i++;
13.
sleep(1);
14.
}
15.
}
16.
17.
18.
void
thread2()
19.
{
20.
21.
while(1)
22.
{
23.
printf(This
is
thread2:%d/n,i);
24.
i++;
25.
sleep(1);
26.
}
27.
}
28.
29.
int
main()
30.
{
31.
pthread_t
t1,t2;
32.
33.
pthread_create(&t1,NULL,(void
*)thread1,NULL);
34.
pthread_create(&t2,NULL,(void
*)thread2,NULL);

阅读全文

与linux线程共享内存相关的资料

热点内容
程序员被公司劝退 浏览:523
java三子棋 浏览:690
加密空间怎么强制进入 浏览:343
ug分割曲线命令 浏览:209
学码思程序员 浏览:609
自考云学习app为什么登不上 浏览:406
domcer服务器昼夜更替怎么搞 浏览:434
plc和单片机哪个好 浏览:535
帝国神话组建云服务器 浏览:827
邓散木pdf 浏览:199
方舟怎么直连服务器图片教程 浏览:563
假相pdf 浏览:336
找对象找程序员怎么找 浏览:976
怎么投诉苹果商店app 浏览:470
华为手机如何看有多少个app 浏览:734
btr如何管理别的服务器 浏览:410
spwm软件算法 浏览:184
70多岁单身程序员 浏览:221
高考考前解压拓展训练 浏览:217
用纸做解压玩具不用浇水 浏览:584