你知道多线程、锁、信息量是什么?有什么用?

你知道多线程、锁、信息量是什么?有什么用?,第1张

线程的概念:

每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由 *** 作系统负责多个线程的调度和执行。

线程是程序中一个单一的顺序控制流程.在单个程序中同时运行多个线程完成不同的工作,称为多线程.

线程和进程的区别在于,子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文.多线程主要是为了节约CPU时间,发挥利用,根据具体情况而定. 线程的运行中需要使用计算机的内存资源和CPU。

多线程的概念

多线程是指从软件或者硬件上实现多个线程并发执行的技术.

你知道多线程、锁、信息量是什么?有什么用?,第2张

多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。

最简单的比喻多线程就像火车的每一节车厢,而进程则是火车。车厢离开火车是无法跑动的,同理火车也不可能只有一节车厢。多线程的出现就是为了提高效率。

如果你的应用程序需要采取以下的 *** 作,那么你尽可在编程的时候考虑多线程机制:

连续的 *** 作,需要花费忍无可忍的过长时间才可能完成

并行计算

所以说,在动手之前,先保证自己的应用程序中是否出现了以上3种情形。

为什么需要多线程(解释何时考虑使用线程)

从用户的角度考虑,就是为了得到更好的系统服务;从程序自身的角度考虑,就是使目标任务能够尽可能快的完成,更有效的利用系统资源。综合考虑,一般以下场合需要使用多线程:

程序包含复杂的计算任务时,主要是利用多线程获取更多的CPU时间(资源)。

处理速度较慢的外围设备.比如:打印时。再比如网络程序,涉及数据包的收发,时间因素不定。使用独立的线程处理这些任务,可使程序无需专门等待结果。

程序设计自身的需要.WINDOWS系统是基于消息循环的抢占式多任务系统,为使消息循环系统不至于阻塞,程序需要多个线程的来共同完成某些任务。

每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由 *** 作系统负责多个线程的调度和执行

线程的优先级

优先级的取值为1-10(数值越高优先级越高)。

Public final int getPriority();  得到线程优先级的数值。

Public final void setPriority(int newPriority);修改线程的优先级。

注:优先级高不代表该线程就一定先运行,只能代表该线程先运行的可能型比较大。

控制线程周期常用的方法

Wait()释放CPU的执行权,释放锁。

NoTIfy()回到wait前的状态。

Yied()让线程临时暂停。(让线程将资源释放出来)

Join()让该线程强行加入执行。

SetDaemon(true)设置该线程为后台线程(当前台线程结束时,后台线程一定会一起结束)。

注:结束线程原理就是让run方法结束,所以只要控制run的流程即可。

为什么要线程同步

线程间共享代码和数据可以节省系统开销,提高效率。但也同时会导致“数据访问冲突”。如何实现线程间有机交互,并确保共享资源在某时只能被一个线程访问,就是线程同步。

多个线程间共享的数据称为临界资源。

多线程的同步与互斥:

方式一:锁

在主线程中初始化锁为解锁状态

pthread_mutex_t mutex;

pthread_mutex_init(&mutex, NULL);

在编译时初始化锁为解锁状态

锁初始化 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

访问对象时的加锁 *** 作与解锁 *** 作

加锁 pthread_mutex_lock(&mutex)

释放锁 pthread_mutex_unlock(&mutex)

互斥锁

每个对象都对应一个互斥锁标记,可以保证在某一时刻只能有一个线程访问该对象。

互斥锁的关键字 synchronized 可以写在某个方法上(代表锁调用该方法的对象);  可以括在要锁的语句外。

好处:解决了线程安全的问题

弊端:降低了运行效率(判断锁,且不能共享信息);容易出现死锁。

死锁:

两个线程A,B用到同一个对象s(s为共享资源),且线程A在执行中要用到B运行后所创造条件。在这种前提下A先开始运行,进入同步块后,对象s被锁定,接着线程A因等待B运行结束而进入阻塞状态,于是B开始运行,但因无法访问对象s,线程B也进入阻塞状态,等待s被线程A解锁。最终的结果:两个线程互相等待,都无法运行。

方式二:信号量

锁有一个很明显的缺点,那就是它只有两种状态:锁定与不锁定。

信号量本质上是一个非负数的整数计数器,它也被用来控制对公共资源的访问。当公共资源增加的时候,调用信号量增加函数sem_post()对其进行增加,当公共资源减少的时候,调用函数sem_wait()来减少信号量。其实,我们是可以把锁当作一个0-1信号量的。

它们是在/usr/include/semaphore.h中进行定义的,信号量的数据结构为sem_t, 本质上,它是一个long型整数

相关函数

在使用semaphore之前,我们需要先引入头文件#include

初始化信号量: int sem_init(sem_t *sem, int pshared, unsigned int value);

成功返回0,失败返回-1

参数

sem:指向信号量结构的一个指针

pshared: 不是0的时候,该信号量在进程间共享,否则只能为当前进程的所有线程们共享

value:信号量的初始值

信号量减1 *** 作,当sem=0的时候该函数会堵塞 int sem_wait(sem_t *sem);

成功返回0,失败返回-1

参数

sem:指向信号量的一个指针

信号量加1 *** 作 int sem_post(sem_t *sem);

参数与返回同上

销毁信号量 int sem_destroy(sem_t *sem);

参数与返回同上

信号量和锁的区别

信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里)。而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源。比如对全局变量的访问,有时要加锁, *** 作完了,在解锁。有的时候锁和信号量会同时使用的”

也就是说,信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后再进行自己下面的步骤,这个任务 并不一定是锁定某一资源,还可以是进行一些计算或者数据处理之类。而线程互斥量则是“锁住某一资源”的概念,在锁定期间内,其他线程无法对被保护的数据进 行 *** 作。在有些情况下两者可以互换。

两者之间的区别:

作用域

信号量: 进程间或线程间(Linux仅线程间的无名信号量pthread semaphore)

互斥锁: 线程间

上锁时 

信号量: 只要信号量的value大于0,其他线程就可以sem_wait成功,成功后信号量的value减一。若value值不大于0,则sem_wait使得线程阻塞,直到sem_post释放后value值加一,但是sem_wait返回之前还是会将此value值减一

互斥锁: 只要被锁住,其他任何线程都不可以访问被保护的资源

以下是信号灯(量)的一些概念:

信号灯与互斥锁和条件变量的主要不同在于”灯”的概念,灯亮则意味着资源可用,灯灭则意味着不可用。如果说后两中同步方式侧重于”等待” *** 作,即资 源不可用的话,信号灯机制则侧重于点灯,即告知资源可用;

没有等待线程的解锁或激发条件都是没有意义的,而没有等待灯亮的线程的点灯 *** 作则有效,且能保持 灯亮状态。当然,这样的 *** 作原语也意味着更多的开销。

信号灯的应用除了灯亮/灯灭这种二元灯以外,也可以采用大于1的灯数,以表示资源数大于1,这时可以称之为多元灯。

原子 *** 作

在多进程(线程)访问共享资源时,能够确保所有其他的进程(线程)都不在同一时间内访问相同的资源。原子 *** 作(atomic operaTIon)是不需要synchronized,这是Java多线程编程的老生常谈了。所谓原子 *** 作是指不会被线程调度机制打断的 *** 作;这种 *** 作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。通常所说的原子 *** 作包括对非long和double型的primiTIve进行赋值,以及返回这两者之外的primitive。之所以要把它们排除在外是因为它们都比较大,而JVM的设计规范又没有要求读 *** 作和赋值 *** 作必须是原子 *** 作(JVM可以试着去这么作,但并不保证)。




 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/2715099.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-17
下一篇 2022-08-17

发表评论

登录后才能评论

评论列表(0条)

保存