2011年1月23日

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.

2010年8月1日

使用SyntaxHighlighter高亮代码

有时候,需要在博客中插入代码片段,一般而言,需求很明确:
  1. 能够针对某一段代码进行语法高亮。
  2. 能够针对某几行代码做「行高亮」处理。
  3. 使用过程中,不需要重复考虑格式化问题。
  4. 支持语言尽可能广泛,目前而言,我需要能够支持 C、Tcl、Python 三种语言。考虑到后续需求,最好也支持 Java、Ruby、Lua 等一票语言。
最后选择了 SyntaxHighlighter(下文简称做 SH)。SH 当前是 v3.0.83 版本,本身不提供 Tcl 语言的支持,我照着官方教程自己写了一份(下载试用)。
考虑到 Tcl 本身是基于字符串的语言(这种机制用多了觉得真是很强大),对于关键字的使用限定很少,譬如你可以写出类似如下的 Tcl 代码:上述代码的第一行、以及第三行中,三个单词分别是「关键字」、「变量名称」、「变量值」。而使用上述的高亮脚本,则不会对此处的命令做语法分析,而将会简单的、将这三个单词全都高亮。而至于这里所定义的 if 函数,直接把 if 给重载了……
不过考虑到 Tcl 语言本身束缚就少,至于可维护性和可读性,更是和使用人员的编程素质密切相关,所以这里也就不纠结了。

更多关于 SyntaxHighlighter 的信息:
  1. 更多配置方式。
  2. SH 3.0 版本所引入的自动加载相应脚本机制

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