PHP信号量基本用法实例详解

这篇文章主要介绍了PHP信号量基本用法,较为详细的分析了PHP信号量的基本概念、使用技巧与相关注意事项,需要的朋友可以参考下。

本文实例讲述了PHP信号量基本用法,分享给大家供大家参考,具体如下:

一些理论基础:

信号量:又称为信号灯、旗语 用来解决进程(线程同步的问题),类似于一把锁,访问前获取锁(获取不到则等待),访问后释放锁。

临界资源:每次仅允许一个进程访问的资源。

临界区:每个进程中访问临界资源的那段代码叫临界区

进程互斥:两个或以上的进程不能同时进入关于同一组共享变量的临界区域,即一个进程正在访问临界资源,另一个进程要想访问必须等待。

进程同步主要研究如何确定数个进程之间的执行顺序和避免数据竞争的问题 即,如何让多个进程能一块很好的协作运行

举例子:(来自百度百科)

以一个停车场的运作为例。简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。

在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

  1. $key=ftok(__FILE__,'t');
  2. /**
  3. * 获取一个信号量资源
  4. int $key [, int $max_acquire = 1 [, int $perm = 0666 [, int $auto_release = 1 ]]]
  5. $max_acquire:最多可以多少个进程同时获取信号
  6. $perm:权限 默认 0666
  7. $auto_release:是否自动释放信号量
  8. */
  9. $sem_id=sem_get($key);
  10. #获取信号
  11. sem_acquire($seg_id);
  12. //do something 这里是一个原子性操作
  13. //释放信号量
  14. sem_release($seg_id);
  15. //把次信号从系统中移除
  16. sem_remove($sem_id);
  17. //可能出现的问题
  18. $fp = sem_get(fileinode(__DIR__), 100);
  19. sem_acquire($fp);
  20. $fp2 = sem_get(fileinode(__DIR__), 1));
  21. sem_acquire($fp2);
  22. Implementation of a read-write semaphore in PHP:
  23. class rw_semaphore {
  24. const READ_ACCESS = 0;
  25. const WRITE_ACCESS = 1;
  26. /**
  27. * @access private
  28. * @var resource - mutex semaphore
  29. */
  30. private $mutex;
  31. /**
  32. * @access private
  33. * @var resource - read/write semaphore
  34. */
  35. private $resource;
  36. /**
  37. * @access private
  38. * @var int
  39. */
  40. private $writers = 0;
  41. /**
  42. * @access private
  43. * @var int
  44. */
  45. private $readers = 0;
  46. /**
  47. * Default constructor
  48. *
  49. * Initialize the read/write semaphore
  50. */
  51. public function __construct() {
  52. $mutex_key = ftok('/home/cyrus/development/php/sysvipc/rw_semaphore.php', 'm');
  53. $resource_key = ftok('/home/cyrus/development/php/sysvipc/rw_semaphore.php', 'r');
  54. $this->mutex = sem_get($mutex_key, 1);
  55. $this->resource = sem_get($resource_key, 1);
  56. }
  57. /**
  58. * Destructor
  59. *
  60. * Remove the read/write semaphore
  61. */
  62. public function __destruct() {
  63. sem_remove($this->mutex);
  64. sem_remove($this->resource);
  65. }
  66. /**
  67. * Request acess to the resource
  68. *
  69. * @param int $mode
  70. * @return void
  71. */
  72. private function request_access($access_type = self::READ_ACCESS) {
  73. if ($access_type == self::WRITE_ACCESS) {
  74. sem_acquire($this->mutex);
  75. /* update the writers counter */
  76. $this->writers++;
  77. sem_release($this->mutex);
  78. sem_acquire($this->resource);
  79. } else {
  80. sem_acquire($this->mutex);
  81. if ($this->writers > 0 || $this->readers == 0) {
  82. sem_release($this->mutex);
  83. sem_acquire($this->resource);
  84. sem_acquire($this->mutex);
  85. }
  86. /* update the readers counter */
  87. $this->readers++;
  88. sem_release($this->mutex);
  89. }
  90. }
  91. private function request_release($access_type = self::READ_ACCESS) {
  92. if ($access_type == self::WRITE_ACCESS) {
  93. sem_acquire($this->mutex);
  94. /* update the writers counter */
  95. $this->writers--;
  96. sem_release($this->mutex);
  97. sem_release($this->resource);
  98. } else {
  99. sem_acquire($this->mutex);
  100. /* update the readers counter */
  101. $this->readers--;
  102. if ($this->readers == 0)
  103. sem_release($this->resource);
  104. sem_release($this->mutex);
  105. }
  106. }
  107. /**
  108. * Request read access to the resource
  109. *
  110. * @return void
  111. */
  112. public function read_access() { $this->request_access(self::READ_ACCESS); }
  113. /**
  114. * Release read access to the resource
  115. *
  116. * @return void
  117. */
  118. public function read_release() { $this->request_release(self::READ_ACCESS); }
  119. /**
  120. * Request write access to the resource
  121. *
  122. * @return void
  123. */
  124. public function write_access() { $this->request_access(self::WRITE_ACCESS); }
  125. /**
  126. * Release write access to the resource
  127. *
  128. * @return void
  129. */
  130. public function write_release() { $this->request_release(self::WRITE_ACCESS); }
  131. }
  132. 共享内存+信号 实现原子性操作
  133. $SHM_KEY = ftok("/home/joeldg/homeymail/shmtest.php", 'R');
  134. $shmid = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
  135. $data = shm_attach($shmid, 1024);
  136. // we now have our shm segment
  137. // lets place a variable in there
  138. shm_put_var ($data, $inmem, "test");
  139. // now lets get it back. we could be in a forked process and still have
  140. // access to this variable.
  141. printf("shared contents: %s\n", shm_get_var($data, $inmem));
  142. shm_detach($data);

以上列子来源php手册 sem_get 函数comment