浅谈Linux多线程编程和Windows多线程编程的异同

对于linux操作系统,互斥也是类似的,只是函数不同罢了。在linux下,和互斥相关的几个函数也要闪亮登场了。

               pthread_mutex_init函数:初始化一个互斥锁;

               pthread_mutex_destroy函数:注销一个互斥锁;

               pthread_mutex_lock函数:加锁,如果不成功,阻塞等待;

               pthread_mutex_unlock函数:解锁;

                pthread_mutex_trylock函数:测试加锁,如果不成功就立即返回,错误码为EBUSY;

    至于这些函数的用法,google上一搜,就出来了,呵呵,在这里不多讲了。windows下还有一个可以用来保护数据的方法,也是线程同步的方式

就是临界区了。临界区和互斥类似。它们之间的区别是,临界区速度快,但是它只能用来同步同一个进程内的多个线程。临界区的获取和释放函数如下:

EnterCriticalSection() 进入临界区; LeaveCriticalSection()离开临界区。 对于多线程共享内存的东东就讲到这里了。

 

  (2)采用消息机制进行多线程通信和同步,windows下面的的消息机制的函数用的多的就是postmessage了。Linux下的消息机制,我用的较少,就不在这里说了,如果谁熟悉的,也告诉我,呵呵。

 

(3)windows下的另外一种线程通信方法就是事件和信号量了。同样针对我开始举得例子,2个线程同步,他们之间传递信息,可以采用事件(Event)或信号量(Semaphore),比如第一个线程完成生产的数据后,就必须告诉第2个线程,他已经把数据准备好了,你可以来取走了。第2个线程就把数据取走。呵呵,这里可以采用消息机制,当第一个线程准备好数据后,就直接postmessage给第2个线程,按理说采用postmessage一个线程就可以搞定这个问题了。呵呵,不是重点,省略不讲了。

对于linux,也有类似的方法,就是条件变量了,呵呵,这里windows和linux就有不同了。要特别讲讲才行。

对于windows,采用事件和信号量同步时候,都会使用waitforsingleobject进行等待的,这个函数的第一个参数是一个句柄,在这里可以是Event句柄,或Semaphore句柄,第2个参数就是等待的延迟,最终等多久,单位是ms,如果这个参数为INFINITE,那么就是无限等待了。释放信号量的函数为ReleaseSemaphore();释放事件的函数为SetEvent。当然使用这些东西都要初始化的。这里就不讲了。Msdn一搜,神马都出来了,呵呵。神马都是浮云!

对于linux操作系统,是采用条件变量来实现类似的功能的。Linux的条件变量一般都是和互斥锁一起使用的,主要的函数有:

pthread_mutex_lock ,

pthread_mutex_unlock,

pthread_cond_init

pthread_cond_signal

pthread_cond_wait

pthread_cond_timewait

为了和windows操作系统进行对比,我用以下表格进行比较:

      

对象

操作

Linux

Windows

线程

创建

Pthread_create

CreateThread/Afxbeginthread

退出

Pthread_exit

ThreadExit

等待

Pthread_join

WaitForSingleObject

互斥锁

创建

Pthread_mutex_init

CreateMutex

销毁

Pthread_mutex_destroy

CloseHandle

加锁

Pthread_mutex_lock

WaitForSingleObject

解锁

Pthread_mutex_unlock

ReleaseMutex

条件变量

创建

pthread_cond_init

CreateEvent

销毁

Pthread_cond_destroy

CloseHandle

触发

pthread_cond_signal

SetEvent

广播

Pthread_cond_broadcast

SetEvent/ResetEvent

等待

Pthread_cond_wait

SingleObjectAndWait

Pthread_cond_timedwait

 

 

 

 

Linux专有的

Pthread_cleanup_push:

Pthread_cleanup_pop:

这两个函数用来保护当程序出现异常时,清除资源等。

Windows专有

Semaphore

 

对照以上表格,总结如下:

(1) Pthread_cleanup_push,Pthread_cleanup_pop:

这一对函数push和pop的作用是当出现异常退出时,做一些清除操作,即当在push和pop函数之间异常退出,包括调用pthread_exit退出,都会执行push里面的清除函数,如果有多个push,注意是是栈,先执行后面的那个函数,在执行前面的函数,但是注意当在这2个函数之间通过return 退出的话,执不执行push后的函数就看pop函数中的参数是不是为0了。还有当没有异常退出时,等同于在这里面return退出的情况,即:当pop函数参数不为0时,执行清除操作,当pop函数参数为0时,不执行push函数中的清除函数。

(2)linux的pthread_cond_signal和SetEvent的不同点

Pthread_cond_singal释放信号后,当没有Pthread_cond_wait,信号马上复位了,这点和SetEvent不同,SetEvent是不会复位的。详解如下:

条件变量的置位和复位有2种常用模型:第一种模型是当条件变量置位时(signaled)以后,如果当前没有线程在等待,其状态会保持为置位(signaled),直到有等待的线程进入被触发,其状态才会变为unsignaled,这种模型以采用Windows平台上的Auto-set Event 为代表。

第2种模型则是Linux平台的pthread所采用的模型,当条件变量置位(signaled)以后,即使当前没有任何线程在等待,其状态也会恢复为复位(unsignaled)状态。

条件变量在Linux平台上的这种模型很难说好坏,在实际应用中,我们可以对

代码稍加改进就可以避免这种差异的发生。由于这种差异只会发生在触发没有被线程等待在条件变量的时刻,因此我们只需要掌握好触发的时机即可。最简单的做法是增加一个计数器记录等待线程的个数,在决定触发条件变量前检查该变量即可。

示例  使用 pthread_cond_wait()  pthread_cond_signal()

 

pthread_mutex_t count_lock;

pthread_cond_t count_nonzero;

unsigned count;

decrement_count()

{

    pthread_mutex_lock(&count_lock);

    while (count == 0)

        pthread_cond_wait(&count_nonzero, &count_lock);

    count = count - 1;

    pthread_mutex_unlock(&count_lock);

}

 

increment_count()

{

    pthread_mutex_lock(&count_lock);

    if (count == 0)

        pthread_cond_signal(&count_nonzero);

    count = count + 1;

    pthread_mutex_unlock(&count_lock);

 

}

 

(3) 注意Pthread_cond_wait条件返回时互斥锁的解锁问题

extern int pthread_cond_wait __P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex));

 调用这个函数时,线程解开mutex指向的锁并被条件变量cond阻塞。线程可以被函数pthread_cond_signal和函数 pthread_cond_broadcast唤醒线程被唤醒后,它将重新检查判断条件是否满足,如果还不满足,一般说来线程应该仍阻塞在这里,被等待被下一次唤醒。如果在多线程中采用pthread_cond_wait来等待时,会首先释放互斥锁,当等待的信号到来时,再次获得互斥锁,因此在之后要注意手动解锁。举例如下:

 

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

 

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /*初始化互斥锁*/

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;  //初始化条件变量

 

void *thread1(void *);

void *thread2(void *);

 

int i=1;

int main(void)

{

        pthread_t t_a;

        pthread_t t_b;

        pthread_create(&t_a,NULL,thread1,(void *)NULL);/*创建进程t_a*/

        pthread_create(&t_b,NULL,thread2,(void *)NULL); /*创建进程t_b*/

        pthread_join(t_b, NULL);/*等待进程t_b结束*/

        pthread_mutex_destroy(&mutex);

        pthread_cond_destroy(&cond);

         exit(0);

}

 

void *thread1(void *junk)

{

        for(i=1;i<=9;i++)

        {

             printf("IN one\n"); 

             pthread_mutex_lock(&mutex);//

           if(i%3==0)

              pthread_cond_signal(&cond);/*,发送信号,通知t_b进程*/

           else      

                  printf("thead1:%d\n",i);

              pthread_mutex_unlock(&mutex);//*解锁互斥量*/

              printf("Up  Mutex\n");     

       sleep(3);

        }

 

}

 

void *thread2(void *junk)

{

        while(i<9)

        {

             printf("IN two \n"); 

              pthread_mutex_lock(&mutex);

            if(i%3!=0)

                   pthread_cond_wait(&cond,&mutex);/*等待*/

            printf("thread2:%d\n",i);

            pthread_mutex_unlock(&mutex);

            printf("Down  Mutex\n");

 

            sleep(3);

 }

 

}

 

输出如下:

IN one

thead1:1

Up  Mutex

IN two

IN one

thead1:2

Up  Mutex

IN one

thread2:3

Down  Mutex

Up  Mutex

IN one

thead1:4

Up  Mutex

IN two

IN one

thead1:5

Up  Mutex

IN one

Up  Mutex

thread2:6

Down  Mutex

IN two

thread2:6

Down  Mutex

IN one

thead1:7

Up  Mutex

IN one

thead1:8

Up  Mutex

IN two

IN one

Up  Mutex

thread2:9

Down  Mutex

 

注意蓝色的地方,有2个thread2:6,其实当这个程序多执行几次,i=3和i=6时有可能多打印几个,这里就是竞争锁造成的了。

引自:http://www.linuxidc.com/Linux/2011-03/33603p2.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值