如何在不同步时钟的情况下对线程强制执行线程锁定(objective-c) [英] How to enforce thread locking on threads with out of sync clocks (objective-c)

查看:76
本文介绍了如何在不同步时钟的情况下对线程强制执行线程锁定(objective-c)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我有两个线程在运行..一个通过网络广播音乐(我们称它为广播台)..另一个与客户端进行通信以了解何时开始广播,播放音乐等.(在主计算机上运行)

basically I got two threads running.. one broadcasts music via a network (let's call it broadcaster).. the other communicates with clients to know when to start broadcasting, play music etc.. (runs on main)

即使服务器正在与客户端通信,广播线程仍在继续运行,当我想暂停广播线程时,只有一部分,那就是当我想向客户端发送数据包以开始播放音乐时(即我希望服务器和客户端都可以同步播放.)

The broadcasting thread keeps on running even while the server is talking to the client, there is only one part when I want to pause the broadcaster thread, and that's when I want to send a packet to the client to start playing music (ie I want both server and client to play in sync)..

我已经使用了几乎所有东西(即NSLocks,pthread_mutex_t和pthread_cond_t,线程睡眠等).但是我继续在这种情况下运行:

I've used pretty much everything (ie NSLocks, pthread_mutex_t and pthread_cond_t, thread sleep etc).. but I keep on running on this scenario:

基本上,我成功地锁定了广播线程..但是它总是在似乎具有不同时钟设置的命令中蔓延

basically I succeed in locking out the broadcaster thread.. but it always creeps in a command that seems to have a different clock setting

注意日志:

12:02:59.288 Snap[30700:7a0f] broadcaster--> sending packet number 69 to all peers
12:02:59.294 Snap[30700:7a0f] broadcaster--> going through packets loop
12:02:59.306 Snap[30700:707] communicator--> SERVER: WILL LOCK BROADCASTING
12:02:59.312 Snap[30700:707] communicator--> we are inside serverReceivedPacket
12:02:59.314 Snap[30700:707] communicator--> SERVER: JUST RECEIVED A PRIMED PACKET!
12:02:59.316 Snap[30700:707]communicator-->  we are inside allPlayersArePrimed and we got 2 players
12:02:59.318 Snap[30700:707] communicator--> CLIENT: players are primed!



12:02:59.320 Snap[30700:707] communicator--> all players are primed now!.. pausing broadcast
12:02:59.322 Snap[30700:707] communicator--> will fire music player
12:02:59.311 Snap[30700:7a0f] broadcaster--> sending packet number 70 to all peers
12:02:59.335 Snap[30700:707] communicator--> SERVER: about to play [UNLOCK]
12:02:59.452 Snap[30700:7a0f] broadcaster--> going through packets loop
12:02:59.454 Snap[30700:7a0f] broadcaster--> sending packet number 71 to all peers

我的问题特别是与此行:

my problem is specifically with this line:

12:02:59.311 Snap[30700:7a0f] broadcaster--> sending packet number 70 to all peers

如果您遵循广播公司的线程日志..您会看到其最后一个日志语句在12:02:59.288停止,然后被锁定了. ..广播公司在12:02:59.311发出了一个命令,尽管它是在及时之后的传播器命令之后

if you follow the broadcaster thread logs.. you'll see that its last log statement stopped at 12:02:59.288, then it was locked out.. but before the communicator unlocked the lock.. the broadcaster threw in a command at 12:02:59.311.. although it came after a communicator command that was later in time!

我已经看到这种情况一次又一次地重复..我不知道该如何解决?

I've seen this scenario repeat time and time again.. and I don't know how to address it?

下面是一些代码:

实例变量已与通信者和广播者共享:

@implementation Game
{
    ... 

    NSLock *broadcastLock;

}

传播者:

    case PacketTypeClientPrimed:
    {

        player.isPrimed = true;  
        if (_state == GameStateWaitingForPrimed && [self allPlayersArePrimed])
        {
            [Logger Log:@"SERVER: WILL LOCK BROADCASTING"];
            broadcastLock = [[NSLock alloc] init];
            [broadcastLock lock];

            _broadCastState = BroadCastStatePaused;
            [hostViewController.musicPlayer skipToBeginning];

            Packet *packet = [Packet packetWithType:PacketTypePlayMusicNow];                

            NSError *error;
            NSLog(@"all players are primed now!.. pausing broadcast ");
            [_session sendDataToAllPeers:[packet data] withDataMode:GKSendDataUnreliable error:&error];
            NSLog(@"will fire music player");

            [self performSelector:@selector(startMusic:) withObject:hostViewController.musicPlayer afterDelay:0.01];
            _state =  GameStatePlayBackCommenced;
        }
    }

....

-(void)startMusic:(MPMusicPlayerController *)player 
{
    NSLog(@"SERVER: about to play [UNLOCK]");
    [player play];
    _broadCastState = BroadCastStateInProgress;
    [broadcastLock unlock];
}

广播公司:

-(void)broadcastSample
{
    [broadcastLock lock];

        CMSampleBufferRef sample;
        sample = [readerOutputcopyNextSampleBuffer];            
        ....                        

        for (int i = 0; i < inNumberPackets; ++i)
        {
            // ..
            // setup audio packet
            // ..
            if ((packetSpaceRemaining < (dataSize + AUDIO_STREAM_PACK_DESC_SIZE)) || 
                (packetDescrSpaceRemaining < AUDIO_STREAM_PACK_DESC_SIZE))
            {
                if (![self encapsulateAndShipPacket:packet packetDescriptions:packetDescriptions packetID:assetOnAirID])
                    break;
            }                        
        }

    [broadcastLock unlock];
}

推荐答案

为什么要动态分配锁对象?当广播者线程通过时,没有锁定对象,因此它不会锁定它.然后,该锁被分配并锁定在通信线程中(无法告诉广播电台已经进入其临界区域),并且两者并行运行.

Why are you allocating the lock object dynamically? When the broadcaster thread goes through there's no lock object, so it doesn't lock it. Then the lock is allocated and locked in the communicator thread (which can't tell the broadcaster has already entered its critical region), and the two run in parallel.

您应该全局分配锁对象,并且该锁对象应该在任一线程可能尝试进入其关键区域之前一直存在.

You should allocate the lock object globally, and it should persist from before the time either thread might attempt to enter its critical region.

这篇关于如何在不同步时钟的情况下对线程强制执行线程锁定(objective-c)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆