多线程,进程,同步互斥

来源:互联网 发布:淘宝上可靠的代购店铺 编辑:程序博客网 时间:2024/06/05 17:30

首先,简单了解三个概念

程序: 静态描述怎么运行的文本,可以说是指令集合

进程: 是具有一定独立功能的程序关于某个数据集合上的一次运行活动(官方解释)

           是系统进行资源分配和调度的一个独立单位. 

线程:进程中单一顺序的控制流。也可以说是轻量级进程。目前程序执行的最小单元。

           是CPU调度和分派的基本单位.他不拥有自己的资源,但共享进程的资源.


【程序】没有资源不能独立运行起来,所以产生了【进程】。一个程序可以有多个进程。

【进程】同一时间不能完全大量的工作,所以将自己分流程了【线程】。一个进程可以有多个线程。

【线程】划分到很细了,他的优点:提高了进程的并发度,有效利用多处理机和多和计算机。


线程与进程的区别:

①、线程是指进程内的一个执行单元,也是进程内的可调度实体.

②、进程有自己的独立地址空间,进程之间资源不共享。线程因为是一个进程分流下来,所以共享资源。(本质区别)

③、线程是处理器调度的基本单位。

④、进程的并发执行属于处理器上的抽象,线程的并发执行则是比进程更深一层的抽象。

简而言之,

线程的划分尺度小于进程,使得多线程程序的并发性高。 
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。


为什么使用多线程:

这个不多说了.....总之就是忙到你想要三头六臂时,他就出现了.

优点:

     1.繁忙的处理或计算一些大数据时,为了保证主线程不一直等待,这种应该交给后台的线程去做.

      2.使资源得到最优化分配.

     3.缩短完成任务的时间

缺点:

     1.操作系统需要切换线程,所以大量使用反而变得更慢

     2.线程多了,BUG也多了

     3.需要更大的内存空间

     4.保证程序的安全性(死锁,中止).



使用线程:

 C/C++

include<thread>;                    //线程的类都在这里 void threadFunc(){                                   //线程内容   std::cout<<"hello world";}int main(){    std::thread   t1=(threadFunc);  //启动线程       t1.join();                   //保证t1执行完毕才主线程才能关闭.     return  0;}
也可以使用λ方式写,总之线程的开源代码:     http://www.oschina.net/question/12_45346


JAVA

第一种方法:  继承thread类

class MyThread  extends  Thread{   public  void  run()  {     //线程内容      }}public  static  void  main( String[ ]  args ){     (  new  MyThread( )   ).start();        //启动线程}

第二种方法: 用Runnable接口  (一般用这种,因为继承只能继承一种,但能对很多种接口

class MyThread  implents  Runnable{   public  void  run()  {     //线程内容      }}public  static  void  main( String[ ]  args ){    ( new thread(  new MyThread( )  ) ).start();        //启动线程}

android

通常创建线程是使用JAVA的上面两种的结合版.

不用继承thread,也不用实现runnable接口直接实例化一个thread,实现runnable的匿名内部类

Thread  mThread = new Thread(new Runnable() {            @Override            public void run() {                try {                    while (true) {                        //线程内容                    }                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });        mThread.start();

安卓的多线程还需要涉及的技术有:handler,Message,MessageQueue,Looper,HandlerThread

在主线程定义handler来对消息进行反应,有Message 和 Post 两种写法

Message写法是要重载handleMessage函数

//Looper.preper();    初始化Looper private Handler handler = new Handler() {            @Override            public void handleMessage(Message msg) {                switch (msg.what) {                case 0://内容                }            }        };//Looper.loop();    启动消息队列
头尾两句只有在子线程中才需要,UI线程中已有消息队列不用绑定了.


在子线程中发送消息

Message message = new Message();message.obj = timer;message.what = 0;handler.sendMessage(message);

POST写法,直接在子线程发送一个runnable,然后主线程中执行

handler.post(new Runnable() {                      @Override    public void run() {         tvMessage.setText("使用Handler.post在工作线程中发送一段执行到消息队列中,在主线程中执行。");                                    }}); 

同步与互斥

用户模式:原子操作,临界区

内核模式:事件,信号量,互斥量


原子操作

不可分割的一个指令,一执行就做到结束为止,不可中断.


临界区

 EnterCriticalSection() 进入临界区  

LeaveCriticalSection() 离开临界区

两个对应着出现.保证单个线程访问数据,其他试图进入的线程将被挂起,直到之前的离开临界区.

实现同进程的线程同步


事件

使用通知的方式,实现不同进程的线程同步

CreateEvent()    创建一个信号量 OpenEvent()    打开一个事件 SetEvent()    回置事件 WaitForSingleObject()   等待一个事件 WaitForMultipleObjects()  等待多个事件WaitForMultipleObjects 函数原型: WaitForMultipleObjects( IN DWORD nCount, // 等待句柄数 IN CONST HANDLE *lpHandles, //指向句柄数组 IN BOOL bWaitAll, //是否完全等待标志 IN DWORD dwMilliseconds //等待时间  ) 


互斥量

每两个线程成互斥,互斥对象只有一个,所以保证数据访问的安全.而且能跨进程实现.

CreateMutex()    创建一个互斥量 OpenMutex()    打开一个互斥量 ReleaseMutex()    释放互斥量 WaitForMultipleObjects() 等待互斥量对象 


信号量

PV操作..,S可以设置初始值,即允许最大有多少个线程访问.

P申请空间:S-1

V释放空间S+1

    CreateSemaphore()  创建一个信号量     OpenSemaphore()  打开一个信号量     ReleaseSemaphore()  释放信号量     WaitForSingleObject()  等待信号量 

#include "stdafx.h"#include "windows.h"#include "stdio.h"volatile int ThreadData = 1;CRITICAL_SECTION csPrint; // 临界区//HANDLE evtPrint; // 事件信号,标记事件是否已发生//HANDLE mtxPrint; // 互斥信号,如有信号表明已经有线程进入临界区并拥有此信号//HANDLE smphPrint; // 信号量,表示是否已经达到允许的最大线程数void Print(char *str){    EnterCriticalSection(&csPrint); // 进入临界区    //WaitForSingleObject(evtPrint, INFINITE); // 等待事件有信号    //WaitForSingleObject(mtxPrint, INFINITE); // 等待互斥量空置(没有线程拥有它)    //WaitForSingleObject(smphPrint, INFINITE); // 等待对共享资源请求被通过 等于 P操作     for (;*str != '\0';str++)    {        Sleep(50);        printf("%c",*str);    }    printf("\n");    LeaveCriticalSection(&csPrint); // 退出临界区    //SetEvent(evtPrint); // 把事件信号量恢复,变为有信号    //ReleaseMutex(mtxPrint); // 释放对互斥量的占有    //ReleaseSemaphore(smphPrint, 1, NULL); // 释放共享资源 等于 V操作 }void ThreadProcess(){    for(int i=0; i<6; i++)    {        Sleep(1000);        Print("Sub  Thread is running!");    }    ThreadData = 0;}int _tmain(int argc, _TCHAR* argv[]){    HANDLE hThread;    DWORD ThreadID;    InitializeCriticalSection(&csPrint); // 初始化临界区    //evtPrint = CreateEvent(NULL, FALSE, TRUE, L"PrintEvent"); // 初始化事件    //mtxPrint = CreateMutex(NULL, FALSE, L"PrintMutex"); // 初始化互斥量    //smphPrint= CreateSemaphore(NULL, 1, 1, L"PrintSemaphore"); // 设置信号量1个资源,因此同时只可以有一个线程访问     hThread=CreateThread(NULL,        0,        (LPTHREAD_START_ROUTINE)ThreadProcess,        NULL,        0,        &ThreadID);    while (ThreadData)    {        Print("Main Thread is waiting for Sub Thread!");        Sleep(600);    }    printf("Main Thread Finished!");    system("pause");    return 0;}


0 0
原创粉丝点击