关于线程安全的一些讨论整理

在多线程编程中,多线程访问的数据安全和完整性问题是大家关注的一个焦点,在实际编程中必需小心谨慎的处理,以保证不会破坏性访问数据。

这里有几个基础的几句话,供大家参考:

(1)、只读不写,对数据是安全的,读到的数据是完整的。

(2)、单写多读,对数据是安全的,但并不代表你读到的数据是完整的。

(3)、同时多写相同位置的内存对数据是具有破坏性的,数据极有可能被破坏的体无完肤。而且你写完后再取数据未必和你写入的数据一致。

(4)、 同时多写一块内存的不同位置对数据是安全的,但同样不代表此时你读到的数据是完整的。

简单解释一下:

(1)、只读就象远观美女,在法律和道德上并没有什么问题,数据美女是安全的。

(2)、就象法律规定一个美女同时只能与一人帅哥结婚一样,单独写相当于独占了这个美女,外人远观对美女没啥影响,但你不能保证某一时刻看到的美女下一时刻是否会因家暴而变丑,从而让观者得到错误的印象。

(3)、一个美女同时与多个帅哥结婚是很恐怖的,美女可能因为法律限制、帅哥打架、家暴等各种原因受到伤害。此时,你得到的美女印象下一时间可能完全不是那么一回事了。

(4)、多个帅哥分别同一群美女中的一个结婚对美女这一群体来说是安全的,没有任何法律风险,不能对美女造成破坏性影响,同原因2观者的印象也可能是不完整的。

在(3)中,一个美女多个帅哥时,美女就成了稀缺资源,产生了资源争用的问题。那么如何解决这一问题呢?

(1)、使用临界锁定

多个帅哥同时争抢美女,但美女只能同时跟一个人结婚,所以,美女就设置了一道令牌(Critical Section),谁第一个抢到(EnterCriticalSection),就得到与美女结婚的权利,其它帅哥只有在美女与前一任离婚后(LeaveCriticalSection)才能重新抢令牌,再与美女结婚。在抢到令牌之前,帅哥们可以选择一直等待(EnterCriticalSection)或者抢下试试(TryEnterCriticalSection)。使用一直等待,帅哥们大好的青春就这么浪费,但使用TryEnterCriticalSection,你就必需在将来的某一个时刻来再次尝试抢令牌,但你的时间不会全浪费在这上面。

(2)、使用事件或信号

同使用临界不同,大家都先在美女那儿登记,说我要与你结婚。美女就象帝皇选妃子侍寝一样,选一个告诉他你跟我结婚吧(触发事件),然后相应的帅哥就急忙去跟美女登记结婚去了。而在离婚后,美女同样会再次重复上面的选择。这样,在某一时间点就保证了只有一对帅哥和美女处于正常的婚姻状态,美女的人身安全都会受到法律的保障。

【注意】

注意,由于Delphi/C++ Builder属性的存在,你认为的只读操作可能牵涉到内存块的写入,如果这样子,访问就会变成不安全的。在确认多线程访问之前,请小心检查系统的源码,以确定多线程访问确实是只读的,不会影响类的成员变量、全局变量的值,而引用的全局或类的成员在访问过程中,不会被其它线程所改变。

 

分享到: