重新启动通用Lisp Bordeaux线程中退出的线程?

时间:2019-03-14 17:08:06

标签: multithreading common-lisp

是否有一种方法可以重新启动已完成其任务的线程,从而避免为下一个任务创建新线程的开销? (请注意,所有其他处理器/线程都将处于繁忙状态,并且(not (bt:thread-alive-p thread)会在线程死时发出信号。)例如,我已经在已完成的线程上尝试了bt:interrupt-thread,但这是行不通的:

* (defparameter *x* 0)
*X*
* (let ((thread (bt:make-thread (lambda () (setf *x* (loop for i from 1 to 10 sum i))))))
    (sleep 1)
    (print *x*)
    (bt:interrupt-thread thread (lambda () (setf *x* (loop for i from 1 to 100 sum i))))
    (sleep 1)
    (print *x*))

55
debugger invoked on a SB-THREAD:INTERRUPT-THREAD-ERROR in thread
#<THREAD "main thread" RUNNING {10012E0613}>:
  Interrupt thread failed: thread #<THREAD "Anonymous thread" FINISHED 
values: 55 {1005D410D3}> has exited.

还有,是否有一种方法可以访问传递给bt:make-thread的函数返回的结果(在线程中),以避免像上面的示例那样通过全局变量进行通信?

1 个答案:

答案 0 :(得分:2)

完成后就完成了。通常的技术是让线程运行一个循环,等待某种通道上的某些工作。

lparallelchanl之类的图书馆可能会有很大帮助。

例如,您可以像这样使用chanl

(defun parallel-mayhem (fun count)
  (let* ((start-chan (make-instance 'chanl:channel))
         (results-chan (make-instance 'chanl:channel)))
    (loop :repeat count
          :do (chanl:pexec ()
                (chanl:send start-chan "starting")
                (chanl:send results-chan (funcall fun))))
    (loop :repeat count
          :collect (chanl:recv start-chan))
    (format t "All started.")
    (loop :repeat count
          :collect (chanl:recv results-chan))))

在后台,chanl使用一个简单的线程池。您可以看看它是如何做到的,它非常简洁易读。