2010年8月2日

Tcl 多线程初步

其实对线程和并发这一块了解相当少,基本上不太清楚究竟什么情况下应该使用并发模型、什么情况下不该采取此类模型。昨天在豆瓣看到一本书,《JAVA并发编程实践》。评价挺高,准备在淘宝入手盗版版本(不是俺想要支持盗版猖獗,只是卓越当当都没货啊。好吧,这其实不是借口…… 囧)。

这里简单的对 Tcl 语言的线程做一下阐述。算是备忘。后续对并发这一块,如果有机会深入了解的话,再补充更新吧。

Tcl 的线程模型主要内容(基于 ActiveTcl 8.5 中包含的 Thread 2.6.5 版本),仅说一下自己觉得印象比较深刻的几点:
  1. 线程的创建、保存、释放等操作。
    thread::create ?-joinable? ?-preserved? ?tcl_script?
    其中开启的 -joinable 参数,可以保证其他的线程来「join」这个线程,从而使得只有当这个线程结束时,join 它的另外一个线程才能够结束。
    thread::wait
    只有通过这条命令创建的线程,才会被启用引用计数机制,才能够执行正常的 thread::preserve 和 thread::release 操作。所有此命令之后的命令,会在线程被释放之后执行(貌似有点类似于析构函数的角色)。
  2. 任何时候,Tcl 如果是以开启线程的方式编译的,那么载入 Thread 包之后,便存在一个主线程。要确保这个「主线程」是最后被中止的。即,这个主线程退出时,不能够存在其他活动的、没有被释放的线程。这一点可以通过上述的 -joinable 参数来保证。具体参见这里
  3. 线程间发送命令。
    thread::send ?-async? $tcl_script
    同步和异步的方式。前者阻塞(不再服务自身的 event loop),后者立即返回。
  4. 错误处理。
    分成若干情况:创建线程、异步发送命令时出错,不写全局错误代码和错误信息,仅仅将错误信息反馈在标准输出上;同步发送命令时出错,错误信息和错误代码将反射到 sender 线程中。置位某个线程的 -unwindonerror 参数后,一旦其执行某命令(其他线程发送给他的命令)出错,此线程即中止。
  5. 线程共享变量。
    每个线程其实都包含一个独立的 Tcl 解释器。然而通过 tsv::set array_name element_name "element_value" 命令创建的共享变量,却可以在各个线程间共享,且不需要考虑线程间写数据的锁机制,这个命令本身就是 atomic 的。在获取的时候之需要使用 tsv::get array_name element_name 就可以了。
  6. 互斥量。条件变量。
    # thread::mutex
    # thread::mutex create
    # thread::mutex destroy $mutex
    # thread::mutex lock $mutex
    # thread::mutex unlock $mutex
    # thread::cond
    # thread::cond create
    # thread::cond destroy $cond
    # thread::cond notify $cond
    # thread::cond wait $cond $mutex
    具体的使用可以参考《Practical Programming in Tcl and Tk》第21章,或者这个链接。前者讲解的挺细致的。
  7. 线程池。
    目前我对这个只有一点概念,勉强大致知道怎么回事。就不多说了。具体可以参考这个链接
    有一点印象深刻:当一个线程给某个线程池 post 命令之后,这条命令本身是 block 的,然而其本身依然是可以服务 event loop 的(并非彻底阻塞了)。
  8. 重复一下,相当于提醒自己。任何命令都需要注意区分,其是否存在阻塞和非阻塞的情况。 阻塞情况下,又要注意区分,此命令执行后,该线程是否还能够服务于自身的 event loop 等等。
最后贴一段代码,写的比较乱,不过基本体现了上述的很多方面(包括线程、线程间共享变量、线程池等等),也体现了当前我对线程这一块的不熟悉。 >_<执行结果如下:
Commands: thread_2 --> thread_1.
Commands: thread_1 --> tpool.
Blocked, still with event loop service.
Commands: thread_2 --> thread_1.
Commands: thread_2 --> thread_1.
Commands: thread_2 --> thread_1.
Commands: thread_2 --> thread_1.
Commands: thread_2 --> thread_1.
tpool job 1 finish.
Commands: thread_2 --> thread_1.
Commands: thread_2 --> thread_1.
Commands: thread_2 --> thread_1.
Commands: thread_2 --> thread_1.
main thread: finished.
thread_2: finished.

3 条评论:

  1. 后续有时间,我还希望能够尽快了解一点Tcl和C混合编程方面的东西。以及Tcl中的Socket部分。

    尽快吧~

    回复删除
  2. 如果时间够充分,可以了解下 Tcl 的源代码。譬如看看其线程的实现等等。
    这部分计划优先级相对较低。C语言这一块还有一些书要好好看,包括《C语言接口与实现》和《The Standard C Library》等等。
    还有算法导论,以及一票数学书。哇靠…… 任务艰巨啊……

    回复删除

不要使用过激的暴力或者色情词汇.
不要充当勇猛小飞侠 --- 飘过 飞过 扑扑翅膀飞走 被雷得外焦里嫩地飞走.
万万不可充当小乌龟 --- 爬过.
构建河蟹社会 责任你有 我有 大家有 -_-

Creative Commons License 转载请指明出处. 谢谢合作.
/***********************
author: jtuki
http://jtuki.blogspot.com/
***********************/