在网上搜了搜,有两个办法但都不太好:一个是简单的以进程id+时间戳,或进程id+随机数来产生近似的唯一id,虽简单但对于追求“完美”的我不愿这样凑合,再说apache2以后进程会维持相当长得时间,生成的id发生碰撞的几率还是比较大的;第二个思路是通过mysql的自增字段,这个就更不能考虑了,效率低不说,我的设计里压根就没数据库。 
递增id的获取是个过程: 
1. 从全局某个存储中读取id 
2. 给id加1 
3. 将id重新存入全局存储 
在多进程或线程的程序中需要将上述3步作为单步的原子操作,才能保证id的唯一。 
java中很好解决,这是因为java程序大多以多线程方式运行,每个线程都能共享java进程中的变量,并能方便的加线程锁控制线程的运转同步。在php中id全局存储没问题,可以放在session中,大不了放在文件中,但进程间同步就是问题了。 
实际上进程调度、管理是操作系统内核必须实现的功能,今天介绍的信号量(也称为信号灯)就是在unix/linux上解决进程同步的一项技术。 
信号灯原是用在铁路上的管理机制,我们今天看到的铁路大多是双线并行,但有的路段受山势、地形影响只有单条铁轨,必须保证同一时间只能有一列火车运行通过这些路段。早先铁路上就是用信号灯来管理的:没有火车经过时,信号等处于闲置状态,一旦有火车进入此路段,信号灯即变为在用状态,其他的火车经过时就需要等待,等待先前的火车驶出路段信号等变为闲置后,才能进入此路段,一旦又有火车进入,信号灯又变为繁忙......,以此来保障铁路运行的安全畅通。 
unix系统就像铁路管理局控制信号灯一样管理控制信号量的状态,因此也可以这样说信号量是由内核管理的,信号量不仅能控制进程间的同步,同样可以控制线程间的同步。 
信号量属于系统进程间通讯技术(ipc),今天我们只从php角度介绍信号量的使用,有关ipc的技术细节可参考stevens的权威著作《unix网络编程第二卷 进程间通信》。 
先看最终的代码:
复制代码 代码如下:
= 1000000000) 
{ 
$id = 1; 
} 
else 
{ 
$id++; 
} 
//将++后的id写入共享内存 
shm_put_var($shm_id, $seq_key, $id); 
//释放信号量,相当于解锁 
sem_release($sem_id); 
//关闭共享内存关联 
shm_detach($shm_id); 
echo 序列号id:{$id}; 
?>
009行,定义了一个16进制的整形key,在php中只支持system v的ipc机制,需要通过一个key关联到指定的资源(消息队列、信号量、共享内存)。 
010 行,定义了一个在共享内存中存储递增id的key,这是php对system v共享内存的闲置:需要通过类似hashtable的key-value方式存储变量。在上面的代码中使用共享内存做id的存储容器,也可以换为 session、文件等其他机制,本文重点是信号量,有关共享内存的知识以后在讲(别忘了前面推荐的那本书)。 
013行,获得系统中的以1234为key的信号量,如果系统中没有就创建一个。 
015行,同13行相似,获得系统中的以1234为key的共享内存,如果系统中没有就创建一个,第二个参数64表示创建64bytes大小的共享内存。 
018~034 行,同步代码区,当一个进程或线程执行sem_acquire函数占有了信号量,到它调用sem_release函数释放信号量的过程内,其他进程或线程执行到sem_acquire会阻塞。021行从共享内存中获得id,函数shm_get_var前缀@是为了屏蔽出错信息(第一次执行时,共享内存中并没有以seq为key的数据,会在页面上打印警告信息)。 
其他语句非常简单,不需多讲。 
程序编好后,访问这个php页面,会递增的输出数字。 
我们可以通过系统命令ipcs查看在程序创建的信号量和共享内存: 
$ ipcs 
------ shared memory segments -------- 
key shmid owner perms bytes nattch status 
0x00001234 1212443 www-data 666 64 0 
------ semaphore arrays -------- 
key semid owner perms nsems 
0x00001234 163841 www-data 666 3 
------ message queues -------- 
key msqid owner perms used-bytes messages 
前两段分别是共享内存和信号量,0x00001234既是我们创建的key。 
也可以通过命令ipcrm删除: 
$ ipcrm -m 0x00001234 #删除共享内存 
$ ipcrm -s 0x00001234 #删除信号量 
--------------------------------------------- 
php手册中关于ipc的资料非常少,这点也不难想象,stevens已经在十几年前讲得透透的东东,在php中只是包装了一下,还有多少必要去深入说明呢? 
文本只是借着id说了说信号量的使用,如果您有更简单的生成自增id的办法,还望赐教。 
可能有朋友还想了解信号量的执行效率,我这里用一句过时的流行语总结: 相当的快。
http://www.bkjia.com/phpjc/320685.htmlwww.bkjia.comtruehttp://www.bkjia.com/phpjc/320685.htmltecharticle在网上搜了搜,有两个办法但都不太好:一个是简单的以进程id+时间戳,或进程id+随机数来产生近似的唯一id,虽简单但对于追求“完美”的...
   
 
   