哲学家用餐模型 分析:为了避免死锁,做了如下规定:每个哲学家先拿自己左手边的筷子,然后再去拿右手边的筷子,如果不能同时得到两支筷子,则该哲学家放下手中已有的筷子。这种规定依然会因为振荡而产生死锁,例如:每个哲学家都同时拿上了左手边的筷子,然后都阻塞,都释放左手筷子;然后又同时去拿左手边的筷子,这样周而复始,一直进行下去,就是因为振荡而产生的死锁。解决方法:规定其中一位哲学家先拿右手边的筷子,再拿左手边的筷子即...
文件锁 借助 fcntl函数来实现文件锁机制。操作文件的进程没有获得文件锁时,可以打开文件,但无法执行read、write操作。 注意,文件锁只能用于进程间同步!fcntl函数:int fcntl(int fd, int cmd);int fcntl(int fd, int cmd, long arg);//long 长整型int fcntl(int fd, int cmd, struct...
进程间同步(互斥量、信号量) 进程间同步可以使用互斥量mutex(互斥锁)、信号量和文件锁。进程间同步使用信号量:int sem_init(sem_t *sem, int pshared, unsigned int value);用于进程间同步此时第二个参数不能取0了,取非0值用于进程间同步,一般取1,也可按照下述方法取值,即:PTHREAD_PROCESS_SHARED。(1)进程间使用互斥量进行同步在p...
信号量 信号量称为进化版的互斥锁。由于互斥锁的粒度比较大,如果我们希望在多个线程间对某一对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住。这样虽然达到了多线程操作共享数据时保证数据正确性的目的,却无形中导致线程的并发性下降。线程从并行执行,变成了串行执行。与直接使用单进程无异。信号量,是相对折中的一种处理方式,既能保证同步,数据不混乱,又能提高线程并发。例如,有5台打印机被多个线...
条件变量 条件变量本身不是锁!但它也可以造成线程阻塞。通常与互斥锁配合使用。给多线程提供一个会合的场所(共享的数据)。主要应用函数:pthread_cond_init函数 pthread_cond_destroy函数pthread_cond_wait函数 pthread_cond_timedwait函数pthread_cond_signal函数 pthread...
读写锁 与互斥量类似,但读写锁允许更高的并行性。其特性为:写独占,读共享。一把读写锁具备三种状态:读模式下加锁状态 (读锁);写模式下加锁状态 (写锁);不加锁状态。引入读写锁的目的:在对共享资源既进行读取,又进行写操作(修改)的情况下,使用读写锁比使用互斥锁(mutex)的效率更高,因为使用读写锁时,允许多个读线程同时读取。特别是当读操作的线程远大于写操作的线程时,这种效果更加明显。(1)读写锁...
死锁 死锁的现象:1. 线程试图对同一个互斥量A加锁两次。这种情况主要是在编程时不经意之间发生的。当对互斥量加锁后,如果再次加锁导致该线程阻塞等待锁被释放,但是该锁其实就被线程自己占有了,因此造成了自己把自己死锁住了。解决方法:在加锁之前应该检查之前是否加过锁还未解锁;2. 当线程要同时获得多个共享资源才能完成工作时,如线程1拥有A锁,请求获得B锁;线程2拥有B锁,请求获得A锁。解决方法:当线程...
互斥量(mutex) Linux中提供一把互斥锁mutex(也称之为互斥量)。每个线程在对资源操作前都尝试先加锁,成功加锁才能操作,操作结束解锁。资源还是共享的,线程间也还是竞争的,但通过“锁”就将资源的访问变成互斥操作,而后与时间有关的错误也不会再产生了。但,应注意:同一时刻,只能有一个线程持有该锁。当A线程对某个全局变量加锁访问,B在访问前尝试加锁,拿不到锁,B阻塞。C线程不去加锁,而直接访问该全局变量,依然能...
线程同步的概念 所谓同步,即同时起步,协调一致。不同的对象,对“同步”的理解方式略有不同。如,设备同步,是指在两个设备之间规定一个共同的时间参考;数据库同步,是指让两个或多个数据库内容保持一致,或者按需要部分保持一致;文件同步,是指让两个或多个文件夹里的文件保持一致。而编程中、通信中所说的同步主旨在协同步调,按预定的先后次序运行。线程同步,指一个线程发出某一功能调用时,在没有得到结果之前,该调用不返回。同时其...
线程使用注意事项 1.主线程退出其他线程不退出,主线程应调用pthread_exit;2.避免僵尸线程:pthread_join、pthread_detach、pthread_create指定分离属性。被join线程可能在join函数返回前就释放完自己的所有内存资源,所以不应当返回被回收线程栈中的值;(因为此时释放的栈空间又可能被重新分配出去,此时得到的返回值没有意义)3.malloc和mmap申请的内存可...
NPTL(Native POSIX Thread Library) 1.NPTL(Native POSIX Thread Library)为POSIX标准线程库,查看当前Linux系统的pthread库(线程库)版本的命令为:getconf GNU_LIBPTHREAD_VERSION。[root@localhost 01_pthread_test]# getconf GNU_LIBPTHREAD_VERSIONNPTL 2.17注意:同样的程序,如果...
线程属性的修改 (1)线程属性Linux下线程的属性是可以根据实际项目需要,进行设置,之前我们讨论的线程都是采用线程的默认属性,默认属性已经可以解决绝大多数开发时遇到的问题。如我们对程序的性能提出更高的要求那么需要设置线程属性,比如可以通过设置线程栈的大小来降低内存的使用,增加最大线程个数。typedef struct{int detach...
线程与进程的控制原语对比 线程与进程的控制原语对比 fork pthead_create exit( int ) pthead_exit(void *); wait(int *) pthread_join( ,void **) 阻塞 ;分离 22 ;cancel -1 kill() ...
pthread_cancel、pthread_equal函数 (1)pthread_cancel函数int pthread_cancel(pthread_t thread); 成功:0;失败:错误号作用:杀死(取消)线程,其作用对应进程中 kill() 函数。注意:线程的取消并不是实时的,而有一定的延时。需要等待线程到达某个取消点(检查点)。杀死线程不是立刻就能完成,必须要到达取消点。取消点:是线程检查是否被取消,并按请求进行动作的一个位置...
pthread_detach函数 int pthread_detach(pthread_t thread); 成功:0;失败:错误号作用:从状态上实现线程分离,注意不是指该线程独自占用地址空间。线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后(不会产生僵尸线程),其退出状态不由其他线程获取,而直接自己自动释放(自己清理掉PCB的残留资源)。网络、多线程服务器常用。进程若有该机制,将不会产生僵尸进程...
pthread_join函数 int pthread_join(pthread_t thread, void **retval);作用:阻塞等待线程退出,获取线程退出状态。其作用对应进程中 waitpid() 函数。成功:0;失败:错误号 strerror函数参数:thread:线程ID (注意:不是指针);retval:存储线程结束状态。对比记忆:在wait回收子进程时,子进程exit或return返回的...
pthread_exit函数 void pthread_exit(void *retval); 参数:retval表示线程退出状态,通常传NULL。作用:将单个线程退出。注意几点:return的作用是返回到函数的调用点,如果是main函数中的return,则代表该进程结束,并释放进程地址空间,所有线程都终止。对于其它函数的return,则直接返回到函数的调用点。exit和_exit函数会直接终止整个进程,导致所有线...
线程共享全局变量(.data和.bbs) 线程默认共享数据段、代码段等地址空间,常用的是全局变量。而进程不共享全局变量,只能借助mmap。//代码示例#include <string.h>#include <stdio.h>#include <pthread.h>#include <stdlib.h>#include <string.h>#include &l...
C指针深度解析 (1)指针的概念指针是一种数据类型,而内存地址是这种数据类型具体的值(注意区分两者的概念)。先说一下什么是内存地址:假设CPU的寻址方式是以字节寻址的,即每一个字节对应一个地址编号(则机器字长、存储字长和数据字长都是字节的整数倍,所有的数据类型占据的空间大小都是字节的整数倍)。对于32位操作系统,地址码最长可达32位,则可以寻址的最大数目为:=4G,由于最小单位是字节,因此可寻址的最大内存为4...
线程控制原语之pthread_self和pthread_create函数 注意:使用线程库函数用gcc编译时,要加参数:-lpthread(libpthread.so),因为线程库函数属于第三方c库函数,不是标准库函数(/lib、/usr/lib或者/usr/local/lib)。(1)pthread_self函数获取线程ID。其作用对应进程中 getpid() 函数。pthread_t pthread_self(void); 返回值:成功:调用该函数的...