mozilla code -nspr 线程同步

来源:互联网 发布:魔仙弓琴(淘宝) 编辑:程序博客网 时间:2024/06/05 09:52

Thread synchronization has two aspects: locking and notification. Locking prevents access to some resource, such as a piece of shared data: that is, it enforces mutual exclusion. Notification involves passing synchronization information among cooperating threads.

//原 文说:nspr4 有两种线程同步方法,线程锁(互斥体)和通知,线程锁保护如共享区数据的一类资源. 通知通过传递同步信息来协作线程.

//线程锁(互斥体,类似与CreateMutex)有:PRLock,  ,PRMonitor,

一.PRLock:

#include "prlock.h"

// 新建一个(初始化)Lock,返回新建的LOCK的句柄.如果没有新建成功,则返回NULL.

//在使用此lock前使用
NSPR_API(PRLock*) PR_NewLock(void);

//销毁一个Lock,在Lock不用的时候销毁它,PR_NewLock的反动作.
NSPR_API(void) PR_DestroyLock(PRLock *lock);


//使用这个Lock,类似与进入互斥一样

NSPR_API(void) PR_Lock(PRLock *lock);


//解锁

NSPR_API(PRStatus) PR_Unlock(PRLock *lock);


//例程:

#include "nspr.h"
//说明上说PR_Lock是用来保护数据的,其实在这段代码中还是用来同步代码的.

#pragma comment(lib,"nspr4.lib")
#pragma comment(lib,"plc4.lib")

PRLock* g_lock;

void Thread_A(char* buf)
{
    PR_Lock(g_lock);//进入锁(保护数据)
    for (int i = 0; i != 10; i++)
    {
        printf("In thread A %d:  %s\n", i,buf);
    }
    PR_Unlock(g_lock);//解锁(其它锁可以进入)
}
void Thread_B(char* buf)
{
    PR_Lock(g_lock);//进入锁(保护数据)
    for (int i = 0; i != 10; i++)
    {
        printf("In thread B %d: \n", i,buf);
    }
    PR_Unlock(g_lock);//解锁(其它锁可以进入)
    }
    

int main(int argc, char* argv[])
{
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
    PRThread* p_tha;
    PRThread* p_thb;
    g_lock = PR_NewLock(); //初始化一个锁(应处理返回NUL的情况)
    p_tha = PR_CreateThread(PR_USER_THREAD,
                                    (void (PR_CALLBACK *)(void *))Thread_A,
                                    "buffer to thread A",
                                    PR_PRIORITY_HIGH,
                                    PR_LOCAL_THREAD,
                                    PR_JOINABLE_THREAD,
                                    0);
    p_thb = PR_CreateThread(PR_USER_THREAD,
        (void (PR_CALLBACK *)(void *))Thread_B,
        "buffer to thread B",
        PR_PRIORITY_NORMAL,
        PR_LOCAL_THREAD,
        PR_JOINABLE_THREAD,
        0);
    PR_JoinThread(p_tha);
    PR_JoinThread(p_thb);
    PR_DestroyLock(g_lock);//主线程结束时锁毁这个锁
    PR_Cleanup();
    return 0;
}

结果

没有加LOCK时输出是这样的:

In thread A 0:  buffer to thread A
In thread B 0:  buffer to thread B
In thread A 1:  buffer to thread A
In thread A 2:  buffer to thread A
In thread B 1:  buffer to thread B
In thread A 3:  buffer to thread A
In thread A 4:  buffer to thread A
In thread B 2:  buffer to thread B
In thread A 5:  buffer to thread A
In thread B 3:  buffer to thread B
In thread A 6:  buffer to thread A
In thread B 4:  buffer to thread B
In thread A 7:  buffer to thread A
In thread B 5:  buffer to thread B
In thread A 8:  buffer to thread A
In thread B 6:  buffer to thread B
In thread A 9:  buffer to thread A
In thread B 7:  buffer to thread B
In thread B 8:  buffer to thread B
In thread B 9:  buffer to thread B


但加了Lock后就是这样了

In thread A 0:  buffer to thread A
In thread A 1:  buffer to thread A
In thread A 2:  buffer to thread A
In thread A 3:  buffer to thread A
In thread A 4:  buffer to thread A
In thread A 5:  buffer to thread A
In thread A 6:  buffer to thread A
In thread A 7:  buffer to thread A
In thread A 8:  buffer to thread A
In thread A 9:  buffer to thread A
In thread B 0:  buffer to thread B
In thread B 1:  buffer to thread B
In thread B 2:  buffer to thread B
In thread B 3:  buffer to thread B
In thread B 4:  buffer to thread B
In thread B 5:  buffer to thread B
In thread B 6:  buffer to thread B
In thread B 7:  buffer to thread B
In thread B 8:  buffer to thread B
In thread B 9:  buffer to thread B

二.PRCondVar

#include "prcvar.h

//创建一个condition varialbe(条件变量),先要创建一个Lock,用Lock来保护condition variable

//有可能返回NULL.
NSPR_API(PRCondVar*) PR_NewCondVar(PRLock *lock);

//销毁一个condition variable,(当此条件变量不再用时)
NSPR_API(void) PR_DestroyCondVar(PRCondVar *cvar);

// 等待一个condition variable(条件变量),如果timeout 是PR_INTERVAL_NO_TIMEOUT则无限等待,

//如果是PR_INTERVAL_NO_WAIT好像是不再等待

//记得一定要先PR_Lock(),完成后PR_Unlock();

NSPR_API(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout);


//通知一个condition variable(条件变量),不管是不是已经接收到.

//记得一定要先PR_Lock(),完成后PR_Unlock();
NSPR_API(PRStatus) PR_NotifyCondVar(PRCondVar *cvar);

//类似于PR_NotifyCondVar,只是通知一组condition variable,不管是不是已经接收到.

//记得一定要先PR_Lock(),完成后PR_Unlock();

NSPR_API(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar);


//例程(vs2008)

#include "nspr.h"


#pragma comment(lib,"nspr4.lib")
#pragma comment(lib,"plc4.lib")

PRIntervalTime start_time;
PRLock* g_lock;
PRCondVar* g_condA;
PRCondVar* g_condB;
//PRMonitor* g_monitor;

void Thread_A(char* buf)
{
    PR_Lock(g_lock);
    for (int i = 0; i != 10; i++)
    {
        PR_WaitCondVar(g_condB, PR_INTERVAL_NO_TIMEOUT); //等待B通知
        printf("In thread A %d:  %s\n", i,buf);
        PR_Sleep(1000); //A处理事件要花点时间
        PR_NotifyCondVar(g_condA); //通知告诉别人说A处理完了
    }        
    PR_Unlock(g_lock);
}
void Thread_B(char* buf)
{
    PR_Lock(g_lock);
    PR_NotifyCondVar(g_condB); //先通知一下,防止相互等待
    for (int i = 0; i != 10; i++)
    {
        PR_WaitCondVar(g_condA, PR_INTERVAL_NO_TIMEOUT);//等待A的通知
        printf("In thread B %d:  %s\n", i,buf);
       PR_NotifyCondVar(g_condB);//B处理事件快,立即通知告诉别人说B完成了
    }
    PR_Unlock(g_lock);
}

int main(int argc, char* argv[])
{
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
    //start_time = PR_IntervalNow();
    //printf("start time:%f\n", (double)PR_IntervalToMicroseconds(PR_IntervalNow() - start_time));
    PRThread* p_tha;
    PRThread* p_thb;
    g_lock = PR_NewLock();
    g_condA = PR_NewCondVar(g_lock);
    g_condB = PR_NewCondVar(g_lock);
    //g_monitor = PR_NewMonitor(); // 初始化monitor
    p_tha = PR_CreateThread(PR_USER_THREAD,
                                    (void (PR_CALLBACK *)(void *))Thread_A,
                                    "buffer to thread A",
                                    PR_PRIORITY_HIGH,
                                    PR_LOCAL_THREAD,
                                    PR_JOINABLE_THREAD,
                                    0);
    //printf("Thread A created time:%f\n", (double)PR_IntervalToMicroseconds(PR_IntervalNow() - start_time));
    p_thb = PR_CreateThread(PR_USER_THREAD,
        (void (PR_CALLBACK *)(void *))Thread_B,
        "buffer to thread B",
        PR_PRIORITY_NORMAL,
        PR_LOCAL_THREAD,
        PR_JOINABLE_THREAD,
        0);
//printf("Thread B created time:%f\n", (double)PR_IntervalToMicroseconds(PR_IntervalNow() - start_time));
    PR_JoinThread(p_tha);
    //printf("Thread A dead time:%f\n", (double)PR_IntervalToMicroseconds(PR_IntervalNow() - start_time));
    PR_JoinThread(p_thb);
    //printf("Thread B dead time:%f\n", (double)PR_IntervalToMicroseconds(PR_IntervalNow() - start_time));
    PR_DestroyLock(g_lock);
    PR_DestroyCondVar(g_condA);
    PR_DestroyCondVar(g_condB);
    PR_Cleanup();
    return 0;
}


三. PRMonitor

#include "prmon.h"

//新建一个monitor(初始化),monitors 是用条件变量实现的可重用的锁 ,

//可能返回NULL(如果内存不足或其它系统资源不足的话)
NSPR_API(PRMonitor*) PR_NewMonitor(void);

//销毁一个monitor ,一定要等到不再使用了再销毁.与PRLock一样.
NSPR_API(void) PR_DestroyMonitor(PRMonitor *mon);


//进入monitor ,并且Lock,不允许其它线程进入,如果本线程已经进入了monitor,那入计数就会加1
NSPR_API(void) PR_EnterMonitor(PRMonitor *mon);


//退出monitor,计数减1.当计数减为0时,则Unlock.

//如果多次进入Moniter,那么就要多次退出Moniter.不然不会Unlock.

//其它线程也就不能得到monitor

NSPR_API(PRStatus) PR_ExitMonitor(PRMonitor *mon);


//先清零计数.然后当前线程暂停,进入等待(_PR_WaitCondVar).当得到其它线程通知或超时后返回

//并恢复计数,线程重新运行.(好像要等通知线程退出monitor才可以重新变为活跃线程)(这里不清楚)

//如果没有进入monitor则返回PR_FAILURE.

//如果ticks为PR_INTERVAL_NO_TIMEOUT则会一直等待.

NSPR_API(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime ticks);


//通知正在等待的线程,(好像不会管有没有收到通知,即便是没有等待线程也会返回)
NSPR_API(PRStatus) PR_Notify(PRMonitor *mon);

//通知所有正在待待的线程.
NSPR_API(PRStatus) PR_NotifyAll(PRMonitor *mon);

//例程(有问题,对Lock的机制还不清楚)

#include "nspr.h"

#pragma comment(lib,"nspr4.lib")
#pragma comment(lib,"plc4.lib")

PRMonitor* g_monitor;

void Thread_A(char* buf)
{
    PR_EnterMonitor(g_monitor);
    for (int i = 0; i != 10; i++)
    {
        printf("In thread A %d:  %s\n", i,buf);
    }    
    PR_Sleep(5000);
    PR_Notify(g_monitor);
    PR_ExitMonitor(g_monitor);
}

int main(int argc, char* argv[])
{
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);

    PRThread* p_tha;

    g_monitor = PR_NewMonitor();

    PR_EnterMonitor(g_monitor);

    p_tha = PR_CreateThread(PR_USER_THREAD,
                                    (void (PR_CALLBACK *)(void *))Thread_A,
                                    "buffer to thread A",
                                    PR_PRIORITY_HIGH,
                                    PR_LOCAL_THREAD,
                                    PR_JOINABLE_THREAD,
                                    0);

        PR_Wait(g_monitor, PR_INTERVAL_NO_TIMEOUT);
        printf("after PR_Wait!") ;

    PR_ExitMonitor(g_monitor);
    PR_JoinThread(p_tha);


    PR_DestroyMonitor(g_monitor);
    PR_Cleanup();
    return 0;
}

三. Cache Monitor

#include "prcmon.h"


// 保护*address 必须用PR_CExitMonitor退出.一一对应

NSPR_API(PRMonitor*) PR_CEnterMonitor(void *address);

//对应于PR_CEnterMonitor
NSPR_API(PRStatus) PR_CExitMonitor(void *address);

//等待一个量,与PR_Wait类似

NSPR_API(PRStatus) PR_CWait(void *address, PRIntervalTime timeout);

//与向PR_CWait发信号,
NSPR_API(PRStatus) PR_CNotify(void *address);

//向所有PR_CWait发信号
NSPR_API(PRStatus) PR_CNotifyAll(void *address);

//例程(vc2008)

#include "nspr.h"

#pragma comment(lib,"nspr4.lib")
#pragma comment(lib,"plc4.lib")

int x = 0;

void Thread_A(char* buf)
{
    PR_CEnterMonitor(&x);
    printf("In thread A %d:  %s\n", x, buf);

    PR_Sleep(5000);
    PR_CNotify(&x);
    PR_CExitMonitor(&x);
}

int main(int argc, char* argv[])
{
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);

    PRThread* p_tha;
    p_tha = PR_CreateThread(PR_USER_THREAD,
                                    (void (PR_CALLBACK *)(void *))Thread_A,
                                    "buffer to thread A",
                                    PR_PRIORITY_HIGH,
                                    PR_LOCAL_THREAD,
                                    PR_JOINABLE_THREAD,
                                    0);

    PR_CEnterMonitor(&x);
    PR_CWait(&x, PR_INTERVAL_NO_TIMEOUT);
    printf("after waiting\n");
    PR_CExitMonitor(&x);
    PR_JoinThread(p_tha);
    PR_Cleanup();
    return 0;
}




原创粉丝点击