Clozure CL で Thread を使ってみる【その2】
Clozure CL で Thread を使ってみる【その1】 - Shammerismの実装では、無限ループ状態になってしまい top で CPU 100% となってしまったのでそうならないように修正を考える。Java の 1.4.2 が最初に本格的に取り組んだ言語だったこともあり、マルチスレッドは wait/notify モデルに慣れていたけれども、Java 5.0 以降は concurrent Package ができて、wait/notify からは徐々にフェードアウトしていったように思われる。なので、あえて wait/notify モデルにこだわらずにセマフォを使ってやってみようと思う。
おそらく、以下を使用すればできるのではないかと。
- make-semaphore
- signal-semaphore
- wait-on-semaphore
とりあえず、以下のようにやってみる。キューにオブジェクトを入れてから semaphore をカウントアップし、キューからオブジェクトを取り出したら semaphore をデクリメントする。と言っても、デクリメントは wait-on-semaphore のブロックを抜けると自動で行われるから意識しなくても大丈夫。
(defparameter *running* t) (defparameter *semaphore* (make-semaphore)) (defmethod take-from-queue ((q queue)) (do () ((not *running*)) (when (wait-on-semaphore *semaphore*) (format t "Take client socket.~%") (let ((client (de-queue q))) (do () () (let ((line (read-line client nil 'eof))) (when (equal line 'eof) (return)) (format t "~A~%" line))) (close-client-socket client))))) (let ((my-queue (create-queue))) (process-run-function "take" 'take-from-queue my-queue) (with-open-passive-socket (server "127.0.0.1" 7001) (let ((client (accept-client-socket server))) (format t "Enqueue Client socket.~%") (en-queue my-queue client) (signal-semaphore))) (format t "finish.~%"))
このファイルを動作させて、nc 127.0.0.1 7001 で接続後に何らかの文字列を送ってみる。結果は以下のようになった。
$ ccl64 -l semaphore-test.lisp Enqueue Client socket. Take client socket. TEST TEST ...
そして、今回の最重要事項、top ではどのようになるかも確認してみたが、CPU は常時 0 % だった。
437 dx86cl64 0.0 00:01.74 4 0 369 4176 14M 14M 0B 0B
これでよし。これに少しずつ改良を加えていけばいいだろう。