1

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

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

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

基本上我成功锁定了广播线程..但它总是在一个似乎有不同时钟设置的命令中爬行

注意日志:

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

我的问题特别在于这一行:

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

如果您关注广播者线程日志..您会看到它的最后一条日志语句在 12:02:59.288 停止,然后它被锁定了..但通信器解锁之前..广播者在 12 处输入了一个命令:02:59.311 ..虽然它是后来的通讯器命令之后出现的!

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

这是一些代码:

与传播者和广播者共享的实例变量:

@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];
}
4

1 回答 1

1

为什么要动态分配锁对象?当广播者线程通过时没有锁定对象,所以它不会锁定它。然后将锁分配并锁定在通信器线程中(它无法告诉广播器已经进入其临界区),两者并行运行。

您应该全局分配锁对象,并且它应该在任一线程可能尝试进入其临界区之前一直存在。

于 2012-11-22T17:34:12.727 回答