28 August 2013

###标题解释

在coding时,有时遇到的问题可以用操作系统的知识来解决.

###问题描述

在一个PHP代码文件里有两段主要代码:其一是提供A数据(这部分代码给个昵称为ACode),其二是提供B数据(这部分代码给个昵称为BCode).其中BCode需要A数据中的部分数据(给个昵称为need)才能计算出B数据.

那么通常的做法就是先执行ACode得到A数据后,BCode再执行不就行了?可如果出现下面这种情况:

假设ACode执行到得到need的时间为t1,执行得到A数据的时间为t2,且t1小于t2很多,那么BCode就要等待很久才执行.也许你会想:那就把BCode放在ACode得到need数据之后执行,但这样的话,ACode剩下的那部分代码就要等到BCode执行完后再执行.

现在需要的实现是:ACode在得到need的时候,BCode就能很快开始执行,而ACode剩下的代码可以和BCode并行执行.

###如何实现?

模拟操作系统进程同步的实现,这里将ACode比喻为ACode进程,BCode比喻为BCode进程.

从问题描述可以看出ACode进程和BCode进程之间存在同步关系,即BCode需要ACode计算出的need数据,且他们之间的制约关系为:直接相互制约(源于进程间的合作).

为了实现ACode进程和BCode进程能在一定程度上并行,需要提供一个输入缓冲区.当ACode进程计算得到need数据后就放入缓冲区中,BCode进程”监听”缓冲区,一旦有数据存入,便取出并计算出B数据.

###PHP代码要如何设计?

首先将ACode和BCode分为两个php代码文件,这里我模拟的是两个ajax并发请求,其中A请求从服务器获取A数据,B请求从服务器获取B数据,ACode和BCode之间的”缓冲区”使用memcached实现.

前台代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Wp Migration</title>
        <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
            <script>
                $(function(){
                    $('#myForm').on('click',function(e){
                         $.ajax({
                            url:'ACode.php',
                            data:$(this).serialize(),
                            type:'GET',
                            success:function(result){
                                $('#result').append(result);
                            }
                        });
                         $.ajax({
                            url:'BCode.php',
                            data:$(this).serialize(),
                            type:'GET',
                            success:function(result){
                                $('#result').append(result);
                            }
                        });
                        return false;
                    });
                });
        </script>
    </head>
    <body>
        <button id="myForm">click</button>
        <div id="result"></div>
    </body>
</html>

ACode代码:

1
2
3
4
5
6
7
8
9
10
11
<?php 
    $memcached = new memcached( 'fetch' );
    $memcached->addServer( '127.0.0.1', 11211 );
    $key = '123456'; //ACode和BCode通信的标识
    $sellerId = 456789;//need数据
    if ( $memcached->add( $key, $sellerId , 100 ) ){
        echo json_encode( array( 'addOk' ) );
    }else{
        echo json_encode( array( 'hasAdd' ) );
    }
?>

BCode代码:

1
2
3
4
5
6
7
8
9
<?php
    $memcached = new memcached( 'fetch' );
    $memcached->addServer( '127.0.0.1', 11211 );
    $key = '123456'; //ACode和BCode通信的标识
    while ( ($value = $memcached->get( $key )) == FALSE) {//"监听"直到ACode将need数据存入"缓冲区"
        //这里可以用sleep()函数设置多久检测一次
    }
    echo json_encode( array($value) );
?>