你得到的问题是,这两条线:
puts [ tsv::get app global_thread_num ]
set thread_id [ tsv::get app global_thread_num ]
不能保证得到同样的价值可言,也不是在有可能与设置同步所有在外部循环中的共享变量。 Tcl中的线程在启动期间具有合理的开销。
相反,你应该做的是让线程与过程中的工作描述一起,然后用ID发送一个简单的消息给他们开始真正的处理;工作起来要容易得多。
package require Thread
puts "*** I'm thread [thread::id]"
for {set thread 1} {$thread <= 200} {incr thread} {
set id [thread::create -joinable {
proc DoWork {thread_id} {
# Only one puts here
puts "${thread_id}thread_id"
set outFile "./test/${thread_id}"
append outFile ".tmd"
puts $outFile
set FileOut [open $outFile w+]
puts $FileOut "${thread_id}thread_id"
# Close the channel, please...
close $FileOut
# Thread done, and since we're using joinable threads it should die now
thread::release
}
thread::wait
}] ;# thread::create
puts "*** Started thread $id"
lappend threadIds $id
# Start the work going, passing over the numeric ID in the "message"
thread::send -async $id [list DoWork $thread]
} ;# for
puts "*** Existing threads: [thread::names]"
# Wait until all other threads are finished
foreach id $threadIds {
thread::join $id
}
puts "*** That's all, folks!"
这里的关键事情是,我们在每一个线程(DoWork
)收到消息,让线程等待消息以thread::wait
,然后通过与thread::send -async
发送消息启动工作创建一个过程。这项工作破坏了thread::release
;它需要明确地这样做,否则它将返回thread::wait
等待下一条消息。
我可能会在生产代码中使用线程池,因为它们更容易扩展到特定部署中可用的硬件。 DoWork
程序 - 无thread::release
- 将在池的-initcmd
选项中定义。 thread::send -async
将被替换为将作品发布到池中,并且您将等待作业而不是线程。
package require Thread
puts "*** I'm thread [thread::id]"
set pool [tpool::create -maxworkers 48 -initcmd {
proc DoWork {thread_id} {
# Only one puts here
puts "${thread_id}thread_id"
set outFile "./test/${thread_id}"
append outFile ".tmd"
puts $outFile
set FileOut [open $outFile w+]
puts $FileOut "${thread_id}thread_id"
# Close the channel, please...
close $FileOut
}
}]
for {set thread 1} {$thread <= 200} {incr thread} {
lappend work [tpool::post -nowait $pool [list DoWork $thread]]
}
# Wait until all work is finished
foreach id $work {
tpool::wait $pool $id
}
puts "*** That's all, folks!"
tpool::release $pool
我假设您正在使用的工作负载更加复杂;只需要在单个线程中完成将单个行写入200个文件中的每个文件。 –
我修改我的tcl文件为你的,它的工作原理。非常感谢你〜我终于找到了我的错误〜哈哈。我使用线程来做一些繁重的工作,而不是只写一行到200个文件中的每一个。 –