
Java 老师希望我们尝试进行 Java 的多线程编程,也希望我们能够去实现一下 C 语言的多线程编程。用以体会不同编程语言间的多线程编程。借此机会,初步学习一下 C 语言的多线程编程。
第一部分主要内容如下:
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。b、 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运行单位。在操作系统的基本概念中进程是程序的一次执行,且是拥有资源的最小单位和调度单位(在引入线程的操作系统中,线程是最小的调度单位)。
单线程程序必须按顺序执行,只有前面的处理好了,后面的才会执行。
单线程有很多缺点,当执行某个耗时或者不能立即完成的任务时,比如:网络通讯、复杂运动,该线程就会暂时停止对其他任务的响应和处理,造成的视觉效果就是程序的假死,也就是应用程序被卡在那里无法继续执行,因此在多数情况下,单线程的应用很少。
而多线程处理可以同时运行多个过程。 当然多线并不同于线程的并行,而是说有一条主线程,处理整个程序任务的主方向的链,而其链上又有许许多多的分支,就像树枝那样,这样,既有了主线程去处理那些主要任务,又有了那些细小线程去处理耗时费力任务,从而让界面看起来更加流畅。
1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程),线程是进程的基本执行单元,一个进程(程序)的所有任务都程中执行。一个进程可以包含若干线程(thread),线程可以帮助应用程序同时做几件事(比如一个线程向磁盘写入文件,另一个则接收用户的按键操作并及时做出反应,互相不干扰),在程序被运行后中,系统首先要做的就是为该程序进程建立一个默认线程,然后程序可以根据需要自行添加或删除相关的线程。为指定进程设置他相对于其它程序的关闭顺序setprocessworkingsetsize 设置操作系统实际划分给进程使用的内存容量setthreadpriority 设定线程的优先级别shellexecute 查找与指定文件关联在一起的程序的文件名terminateprocess 结束一个进程winexec 运行指定的程序adjustwindowrect 给定一种窗口样式。

如果要形象一点比喻,那就是: 大家在食堂吃饭的经历,尤其是学校里面的食堂。饭堂会有学生访问高峰,这就需要卖饭的大妈,身手矫健,要记下学生点的饭,之后一边做饭,一边装饭。如果生意实在太好,可以多雇人手,一起帮着卖饭。
一个食堂大妈就是进程,记菜单,做饭,装饭这些动作就是进程中线程。如果想要快速完成这些动作,食堂大妈就要在记菜单,做饭,装饭之间不停的切换,这个就是多线程。如果增加人手这个就相当于计算机增加 cpu 内核,他们都可以独立执行线程,这也是多线程。
若要总结一句就是: 进程是资源分配的最小单位,线程是 CPU 调度的最小单位。
5s 读取文件A
2s 处理文件A
5s 读取文件B
2s 处理文件B
-------------
总共需要 14 s
为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。正是这样的读取机制使cpu读取缓存的命中率非常高(大多数cpu可达90%左右),也就是说cpu下一次要读取的数据90%都在缓存中,只有大约10%需要从内存读取.这大大节省了cpu直接读取内存的时间,也使cpu读取数据时基本无需等待.总的来说,cpu读取数据的顺序是先缓存后内存.。在磁盘地址表中有13个块号,文件将以块号在磁盘地址表中出现的顺序依次读取相应的块。
5s 读取文件A
5s 读取文件B + 2s 处理文件A
2s 处理文件B
-------------
总共需要 12 s
CPU 等待第一个文件被读取完。然后开始读取第二个文件。当第二文件在被读取的时候,CPU 会去处理第一个文件。记住,在等待磁盘读取文件的时候,CPU 大部分时间是空闲的。

总的说来,CPU 能够在等待 IO 的时候做一些其他的事情。这个不一定就是磁盘 IO。它也可以是网络的 IO,或者用户输入。通常情况下,网络和磁盘的 IO 比 CPU 和内存 的IO慢的多。
这跟小学生做的数学题中关于合理安排煮水洗衣服时间的问题是一样的。
在单线程应用程序中,如果想编写程序手动处理上面所提到的读取和处理的顺序,就必须记录每个文件读取和处理的状态。如果采取多线程编程,那么可以启动两个线程,每个线程处理一个文件的读取和操作。线程会在等待磁盘读取文件的过程中被阻塞。在等待的时候,其他的线程能够使用 CPU 去处理已经读取完的文件。其结果就是,磁盘总是在繁忙地读取不同的文件到内存中。这会带来磁盘和CPU 利用率的提升。而且每个线程只需要记录一个文件,因此这种方式也很容易编程实现。
将一个单线程应用程序变成多线程应用程序的另一个常见的目的是实现一个响应更快的应用程序。设想一个服务器应用,它在某一个端口进来的请求。当一个请求到来时,它去处理这个请求,然后再返回去。
服务器的流程如下所述:
while(server is active){
listen for request
process request
}
取消线程的操作主要应用于下列场景中:有一个线程在使用select监控网口,主控线程此时接到了用户的通知,要放弃,则主控线程会向线程发送取消请求。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。另外木马程序的server端为了隐藏自己,必须在设计中做到不让自己显示到任务栏或者系统进程控制器中,同时还不会影响其他程序的正常运行,当使用者电脑处于断线状态下,server段不会发送任何信息到预设的端口上,而会自动检测网络状态直到网络连接好,server会通过email或者其他形式将server端系统资料通知client端,同时接收client发送出来的请求。

while(server is active){
listen for request
hand request to worker thread
}
其实ajax实现同步和异步很简单c 多线程 多任务,只要设置async的属性值就行,默认的设置值为true,这种情况为异步方式,就是说当ajax发送请求后,在等待server端返回的这个过程中,前台会继续 执行ajax块后面的脚本,直到server端返回正确的结果才会去执行success,也就是说这时候执行的是两个线程,ajax块发出请求后一个线程 和ajax块后面的脚本(另一个线程),两个线程互不影响。第一步,客户端发送不带authentication header的http请求,服务器检查后发现受访的资源需要认证,就会返回http status 401,表示未授权,客户端发现服务器端返回401后,会再构造一个新的请求,这次包含了authentication header,服务器接收后验证通过,返回资源。当客户端请求建立某个c/s应用请求时,rap服务器端会主动push一个java applet到客户端,实时客户端到当前c/s应用的原内网地址信息和端口,协议信息等,客户端java applet把到所有信息通过ssl加密后在internet上传回到rap服务器上,rap服务器解密该数据包,把这些原始信息像在内网的访问一样传给真正的内部c/s服务器,内网c/s应用服务器正常响应此请求,像内网访问一样返回数据包到rap,rap加密此数据包通过internet传输给远程的客户端。
桌面应用也是同样如此。如点击一个按钮开始运行一个耗时的任务,这个线程既要执行任务又要更新窗口和按钮,那么在任务执行的过程中,这个应用程序看起来好像没有反应一样。相反,任务可以传递给工作者线程(word thread)。当工作者线程在繁忙地处理任务的时候,窗口线程可以自由地响应其他用户的请求。当工作者线程完成任务的时候,它发送信号给窗口线程。窗口线程便可以更新应用程序窗口,并显示任务的结果。对用户而言,这种具有工作者线程设计的程序显得响应速度更快。
一个线程可以调用pthread_mutex_lock获得mutex(操作系统调度执行此线程),如果这时另一个线程已经调用pthread_mutex_lock获得了该mutex,则当前线程需要挂起等待(操作系统仍可能在调度执行此线程),(操作系统调度切换运行另一线程)直到另一个线程调用pthread_mutex_unlock释放mutex,(另一线程释放mutex时操作系统调度运行此线程)当前线程被唤醒(即从此线程上次执行的地方继续执行),才能获得该mutex并继续执行。将a、b两道程序同时存放在内存中,它们在系统的控制下,可相互穿插、交替地在cpu上运行:当a程序因请求i/o操作而放弃cpu时,b程序就可占用cpu运行,这样 cpu不再空闲,而正进行a i/o操作的i/o设备也不空闲,显然,cpu和i/o设备都处于“忙”状态,大大提高了资源的利用率,从而也提高了系统的效率,a、b全部完成所需时间< 列举几个多线程的应用场景: 为不阻塞主线程(UI线程),使用其他线程处理事务 加快访问 Web 访问速度。主线程来专门请求,子线程专门来处理请求,可以获得大的吞吐量。 某种由于优先级很低的服务,却又要不定时去做的c 多线程 多任务,比如 JVM 的垃圾回收 FTP,IDM 下载,多线程操作文件 大量数据插入,采用合适数量的线程 … Linux 操作系统使用符合 POSIX 线程作为系统标准线程,该 POSIX 线程标准定义了一整套操作线程的 API。Pthread 是 POSIX threads 的简称,是 POSIX 的线程标准。学会创建线程是多线程编程的第一步,理解线程如何创建是进行多线程编程的关键。 一个线程的生命周期起始于它被创建的那一刻,创建线程的接口: 函数参数: 当置第二、第四个参数为 NULL 的时候,则创建默认线程。 函数返回值:
#include <pthread.h>
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg
);
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-107160-1.html
有钱了说句屁话都被人捧为经典