Delphi管理多线程之线程局部存储:threadvar

  尽管多线程能够解决许多问题,但是同时它又给我们带来了很多的问题。其中主要的问题就是:对全局变量或句柄这样的全局资源如何访问?另外,当必须确保一个线程中的某些事件要在另一个线程中的其他时间之前(或之后)发生时,该怎么办?这里将讲解通过使用由 Delphi提供的线程局部存储和 A P I为线程提供同步的方法。

  这里先讲线程局部存储,下一篇再讲线程同步

线程局部存储

  由于每个线程都代表一个不同的执行路径,因此,最好有一种只限于一个线程内部使用的数据存储方式。要实现上述目的有三种方式:

1)第一种也是最简单的一种方式是局部变量((基于栈)。

  由于每个线程都在各自的栈中,各个线程都将有一套局部变量的副本,这样,就不会互相影响。

2)第二种方式就是把有关信息保存在各自的线程对象中

3)第三种方式就是用Delphi的关键字 threadvar 来声明变量,以利用操作系统级的线程局部存储

1.把信息保存在TThread派生对象中

  将相关信息保存在TThread派生对象中,这是一种线程局部存储可选的技术。相对于使用关键字threadvar的技术,这种方式更加简单、更加有效。例如,你可以在一个线程对象中加入下列信息

1
2
3
4
5
6
7
8
type
    TMyThread = class(TThread)
    private
        FLocalInt: Integer;
        FLocalStr: String;
        ..
        ..
    end;

  提示:由于访问线程对象中的数据比访问线程局部变量快10倍,因此,你应当尽可能地把线程专用的信息保存在线程对象中。对于那些只在过程或函数的生存期有意义的变量,应当把它们声明为局部变量

2.threadvar:API线程局部存储

  在前面讲到:虽然对于局部变量,在每个线程中都有一个副本,然而应用程序的全局变量是被所有线程所共享的。例如,假设现在还有一个用于设置和显示一个全局变量的值的过程。如果传递一个字符串给它,就设置这个全局变量;如果传递一个空字符串给它,就显示这个全局变量的值。这个过程定义如下:

1
2
3
4
5
6
7
8
9
var
    GolbalStr: String;
procedure SetShowStr(const S: String);
begin
    if S = '' then
        MessageBox(0PChar(GlobalStr), 'The string is ...', MB_OK)
    else
        GlobalStr:= S;
end;

  如果在某段代码中调用这个过程,则可能出现一些问题。因为在调用它时,可以先设置而后显示。可问题是,有可能有两个或更多的线程存在。当一个线程调用此过程来设置字符串时,而另一个线程也可能调用此过程来设置GlobalStr 变量的值。当操作系统把CPU时间又分配给前一个线程时,该线程所设置的值有可能已经令人失望的丢失了

  为了解决这个问题,Win32 提供了一种称为线程局部存储的方式,它能使你在第一个运行的线程中创建一个全局变量的拷贝。Delphi利用关键字 threadvar封装此功能。

  在threadvar关键字下你可以声明任何局部存储的变量。下面是局部变量GlobalStr的声明:

1
2
threadvar
    GlobalStr: String;

  下面演示了线程局部存储的用法。在程序的主窗体上有一个按钮,单击此按钮,就设置并显示 GlobalStr变量的值。然后再创建一个线程,GlobalStr变量的值有被设置并显示。在创建了一个线程之后,从主线程再次设置并显示GlobalStr变量的值

  先后用var 和 threadvar来声明 GlobalStr变量并运行此程序,你会在输出中看到不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
interface
uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;
 
type
    TMainForm = class(TForm)
        Button1:TButton;
        procedure Button1Click(Sender: TObject);
    private
        {...}
    public
        {...}
    end;
 
var
    MainForm: TMainForm;
 
implementation
{$R *.DFM}
 
var
//threadvar
    GlobalStr: String;
 
type
    TTLSThread = class(TThread)
    private
        FNewStr: String;
    protected
        Procedure Execute; override;
    public
        cpnstructor Create(Const ANewStr: String);
    end;
 
procedure SetShowStr(const S: String);
begin
    if S = '' then
        MessageBox(0PChar(GlobalStr), 'The string is ...', MB_OK)
    else
        GlobalStr:= S;
end;
 
constructor TTLSThread.Create(const ANewStr: String);
begin
    FNewStr:= ANewStr;
    inherited Create(False);
end;
 
procedure TTSThread.Execute;
begin
    FreeOnTerminate:= True;
    SetShowStr(FNewStr);
    SetShowStr('');
end;
 
procedure TMianForm.Button1Click(Sender: TObject);
begin
    SetShowStr('Hello World');
    SetShowStr('');
    TTLSThread.Create('Dilbert');
    Sleep(100);
    SetShowStr('');
end;
 
end.

  注意:演示程序中,在创建了线程之后,调用了一个Win32 API过程 Sleep()。此过程的声明如下

1
procedure Sleep(dwMillseconds: DWORD); stdcall;

  Sleep()过程用来告诉操作系统,当前的线程在参数 dwMillseconds指定的时间内不需要分配任何CPU时间。插入这个调用是使很多的任务在发生时,使执行哪个线程有一些随机性

  通常,可以把参数dwMillseconds设置为0,尽管,这并没有使当前的线程真的“睡眠”,但是它使操作系统把CPU时间分给其他优先级相等或者更高的线程

  要小心Sleep()神秘的时间调整问题。Sleep()可能会是你的机器出现特别的问题。这种问题在另一台机器上可能无法再现

https://www.cnblogs.com/xumenger/p/4450634.html

多线程threadvar 变量设定的更多相关文章

  1. Java多线程中变量的可见性

    之所以写这篇博客, 是因为在csdn上看到一个帖子问的就是这个问题. 废话不多说, 我们先看看他的代码(为了减少代码量, 我将创建线程并启动的部分修改为使用方法引用). 1 2 3 4 5 6 7 8 ...

  2. c/c++ 多线程 利用条件变量实现线程安全的队列

    多线程 利用条件变量实现线程安全的队列 背景:标准STL库的队列queue是线程不安全的. 利用条件变量(Condition variable)简单实现一个线程安全的队列. 代码: #include ...

  3. Python_关于多线程下变量赋值取值的一点研究

    关于多线程下变量赋值取值的一点研究 by:授客 QQ:1033553122 1.代码实践1 #!/usr/bin/env python # -*- coding:utf-8 -*- __author_ ...

  4. 变量的取用与设定:echo,变量设定规则,unset

    1.变量的取用echo echo $variable echo ${variable} 2.变量的设定规则 3.让我设定的name=VBird应用在下个应用程序 4.进入到核心的模块目录 5.取消设定 ...

  5. Linux Qt使用POSIX多线程条件变量、互斥锁(量)

    今天团建,但是文章也要写.酒要喝好,文要写美,方为我辈程序员的全才之路.嘎嘎 之前一直在看POSIX的多线程编程,上个周末结合自己的理解,写了一个基于Qt的用条件变量同步线程的例子.故此来和大家一起分 ...

  6. JAVA基础学习——1.3 关于JAVA环境变量设定 Path,Java_Home,ClassPath

    在安装完JDK以后,要设定JAVA环境变量. 刚接触的时候,我很困惑,这特么什么玩意啊,然后知其然不知其所以然的 按照说明做完了却不知道为什么这么做,这里简单做一些总结说明. 首先,什么是环境变量 环 ...

  7. Linux 多线程条件变量同步

    条件变量是线程同步的另一种方式,实际上,条件变量是信号量的底层实现,这也就意味着,使用条件变量可以拥有更大的自由度,同时也就需要更加小心的进行同步操作.条件变量使用的条件本身是需要使用互斥量进行保护的 ...

  8. [转] 多线程下变量-gcc原子操作 __sync_fetch_and_add等

    http://blog.sina.com.cn/s/blog_6f5b220601013zw3.html 非常好的原子操作,不用加锁:__sync_fetch_and_add GCC 提供的原子操作 ...

  9. C++11并发——多线程条件变量std::condition_variable(四)

    https://www.jianshu.com/p/a31d4fb5594f https://blog.csdn.net/y396397735/article/details/81272752 htt ...

随机推荐

  1. JS鼠标响应事件经过、移动、点击示例介绍

    原文: http://www.jb51.net/article/41124.htm onMouseDown 按下鼠标时触发 onMouseOver 鼠标经过时触发 onMouseUp 按下鼠标松开鼠标 ...

  2. 七大查找算法(Python)

    查找算法 -- 简介 查找(Searching)就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素.    查找表(Search Table):由同一类型的数据元素构成的集合    ...

  3. 2014-10-23 NOIP模拟赛

    NOIP2014模拟赛 -----lwher 时限均为1s,内存 256MB 1.Jams倒酒(pour) Jams是一家酒吧的老板,他的酒吧提供2种体积的啤酒,a ml 和 b ml,分别使用容积为 ...

  4. 【NOIP模拟】序列

    [问题描述] 一个序列被称为有趣的序列是它的所有的子串拥有一个唯一的整数(这个整数在整个序列中只出现过一次).给你一个序列的整数, 问你它是否是有趣的. [输入格式] 第一行 T, 表示数据组数.接下 ...

  5. netty与MQ使用心得

    最近在做分布式的系统,使用netty与mq进行远程RPC调用,现将心得经验总结一下. 我们公司的服务器在云端机房,在每一个店面有一个服务器,店面服务器外网无法访问. 我们的做法是店面服务器在启动时与云 ...

  6. [软件工程基础]2017.11.02 第六次 Scrum 会议

    具体事项 燃尽图 每人工作内容 成员 已完成的工作 计划完成的工作 工作中遇到的困难 游心 #10 搭建可用的开发测试环境:#9 阅读分析 PhyLab 后端代码与文档:#8 掌握 Laravel 框 ...

  7. ZROI 普及组模拟赛02总结

    ZROI 普及组模拟赛02总结 先放[网址][http://zhengruioi.com/contest/96] 可能是有一段时间没有打这种正式的比赛了,今天打的很奇怪... T1 模拟水题 既然是普 ...

  8. HDU-1003:Max Sum(优化)

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  9. 2017"百度之星"程序设计大赛 - 资格赛 寻找母串

    Problem Description 对于一个串S,当它同时满足如下条件时,它就是一个01偏串: 1.只由0和1两种符组成: 2.在S的每一个前缀中,0的个数不超过1的个数: 3.S中0的个数和1的 ...

  10. 《深入理解java虚拟机》笔记(1)运行时数据区域

    1.Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来. 2.运行时数据区域划分 java虚拟机在执行java程序的过程中会把它所管理的内存划 ...