<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="/Skins/Default/Rss.xsl" ?>
<rss version="2.0">
<channel>
<title>Căn bản về .NET Framework : Giải phóng bộ nhớ</title>
<link>http://dot.net.vn/Desktop.aspx/Threads/CanBan-dotNET-Framework/Giai_phong_bo_nho/</link>
<description>Vì chưa hiểu sâu về cơ chế giải phóng bộ nhớ trong .NET, mình có đặt ra một ví dụ như sau:&lt;br&gt;
&lt;br&gt;
class A: IDisposable&lt;br&gt;
{&lt;br&gt;
	private B _b;&lt;br&gt;
	&lt;br&gt;
	public A()&lt;br&gt;
	{}&lt;br&gt;
	&lt;br&gt;
	public void Dispose()&lt;br&gt;
	{&lt;br&gt;
		_b = null;&lt;br&gt;
	}&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
Trong hàm Dispose() của lớp A mình có gán _b = null, với các
gán này thì vùng nhớ của _b trong HEAP không bị giải phóng
phải không?&lt;br&gt;
Vậy làm các nào nếu một instance của A bị Dispose thì _b phải bị dispose theo?&lt;br&gt;1/ _b chưa chắc đã nằm trong heap. Tùy thuộc class B của bạn là gì, reference type hay value type.&lt;br&gt;
&lt;br&gt;
2/ _b = null không hề dispose _b. khi bạn khai báo:&lt;br&gt;
    private B _b;&lt;br&gt;
&lt;br&gt;
   tương đươhg với khai báo 1 pointer _b.&lt;br&gt;
   Khi bạn instantiate _b như sau:&lt;br&gt;
   _b = new B();&lt;br&gt;
&lt;br&gt;
  thì một instance của class B mới được khởi tạo và pointer _b được gán để trỏ tới instance này.&lt;br&gt;
&lt;br&gt;
  Do đó, khi bạn gán _b = null đơn thuần chỉ là gán pointer _b tới nothing.&lt;br&gt;
&lt;br&gt; Vậy khi A bị thì _b có dispose hay không? Không. Trừ phi class B
implements IDisposable và bạn gọi cụ thể _b.Dispose() thì GC sẽ cho
phép _b được dispose (nhưng chưa chắc đã bị finalized hoặc collected)&lt;br&gt;
&lt;br&gt; Vậy khi A bị collected (giải phóng bộ nhớ) thì _b có bị collected
không? Câu trả lời là tùy. Nếu A instantiate _b và không có bất kỳ
object nào khác reference đến _b (nói cách khác là cả _b và A đều goes
out of scope) thì khi A bị collected, _b cũng sẽ bị collected theo, cho
dù bạn có gán _b = null hay không cũng vậy.&lt;br&gt;
&lt;br&gt;
 Bạn nên lưu ý là các khái niệm này rất khác nhau: dispose, finalize, collected.&lt;br&gt;&lt;br&gt;Để hiểu rõ hơn về Garbage Collection trong .NET, bạn hãy xem 2 bài viết này:&lt;br&gt;
&lt;br&gt;
&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/dotnetGCbasics.asp" target="_blank"&gt;http://msdn.microsoft.com/library/de...etGCbasics.asp&lt;/a&gt;&lt;br&gt;
(Chú trọng tới performance)&lt;br&gt;
&lt;br&gt;
&lt;a href="http://www.codeproject.com/dotnet/garbagecollection.asp" target="_blank"&gt;http://www.codeproject.com/dotnet/garbagecollection.asp&lt;/a&gt;&lt;br&gt;
(Chú trọng tới algorithms)&lt;br&gt;&lt;br&gt;&lt;b&gt;1/Sự khác biệt giữa Dispose, Finalize, và Collect:&lt;/b&gt;&lt;br&gt;
       &lt;b&gt;IDisposable.Dispose():&lt;/b&gt;
Dùng để ra lệnh cho GC chú ý giải phóng resources của 1 object khi lập
trình viên biết rõ khi nào thì cần giải phóng. Lưu ý là khi implement
IDisposable phải quan tâm tới chuyện Dipose() sẽ bị gọi 1, 2, nhiều,
hoặc thậm chí không có lần nào cả. Chưa hết chuyện, mặc dù Dipose()
dùng để freeup resources. GC có thích freeup hay không thì... hãy đợi
đấy &lt;br&gt;
        Ngoài ra, implement IDisposable thì cũng không đơn giản chỉ là override Dispose() đâu:&lt;br&gt;
&lt;a href="http://www.vbinfozine.com/a_disposable.shtml" target="_blank"&gt;http://www.vbinfozine.com/a_disposable.shtml&lt;/a&gt;&lt;br&gt;
(xem chơi cho biết, trong bài viết có link tới cách chính thức implement IDisposable của MSDN)&lt;br&gt;
&lt;br&gt;
       &lt;b&gt;Finalize:&lt;/b&gt; IDisposable.Finalize() thực ra chẳng cần
thiết bởi vì khi có destructor ~Class(), tự động nó sẽ ngầm gọi
Finalize() từ base class rồi.&lt;br&gt; Nếu trong các ngôn ngữ khác như
Delphi chẳng hạn, Finalize chính là finalize thực sự. Có nghĩa là:
những điều tôi cần phải làm trước khi tôi chết. Còn trong .NET thì hoàn
toàn lại khác hẳn: tôi chết rồi, xí quên, tui còn cái list finalize cần
phải làm, &lt;b&gt;hãy cho tui sống lại cùng với bè bạn của tui (referenced resources)&lt;/b&gt;
để cho tui hoàn tất finalize rồi mới cho tui chết. Do đó, khi class có
finalize hoặc disposable chỉ tổ làm cho garbage collection chậm hơn
nhiều lần.&lt;br&gt; Nói ngắn gọn: tốt nhất là đừng có destructors, đừng có
IDiposable. Chỉ dùng khi bắt buộc phải nói chuyện với unmanaged
resources.&lt;br&gt;
&lt;br&gt;
       &lt;b&gt;Collection:&lt;/b&gt; sau khi object bị đưa vào "danh sách tử
thần", nếu không bị Finalize cứu trở vô danh sách luân hồi, thì GC sẽ
nhí nhảnh lựa ra vài em rồi... trảm. &lt;br&gt;
       Xem ví dụ này để thấy GC nhí nhảnh như thế nào. Bạn cũng có thể dựa vào code sườn này để phát triển thêm tests khác.&lt;br&gt;
&lt;a href="http://www.csharphelp.com/archives/archive180.html" target="_blank"&gt;http://www.csharphelp.com/archives/archive180.html&lt;/a&gt;&lt;br&gt;&lt;br&gt;1/ &lt;b&gt;volatile&lt;/b&gt; hay &lt;b&gt;lock&lt;/b&gt; đều tương đương với:&lt;br&gt;
    Monitor.Enter(lockingObject);&lt;br&gt;
    ....&lt;br&gt;
    Monitor.Exit(lockingObject);&lt;br&gt;
&lt;br&gt;
    Do đó, bạn dùng volatile và lock cùng lúc là thừa. Bản thân volatile đã bắt buộc "dirty-read", dẫn tới Monitor rồi.&lt;br&gt;
&lt;br&gt;
2/ lock toàn bộ class chi vậy bạn? Khi lock thì chỉ nên lock càng ít
càng tốt. Thay vì lock(typeof(SingletonA)); bạn có thể làm như sau:&lt;br&gt;
   static readonly object lockingObject;&lt;br&gt;
   ....&lt;br&gt;
  get&lt;br&gt;
  {&lt;br&gt;
      lock(lockingObject)&lt;br&gt;
      {&lt;br&gt;
           .....&lt;br&gt;
      }&lt;br&gt;
  }&lt;br&gt;
&lt;br&gt;
3/ Ngoài vấn đề volatile và lock ra thì cả 2 class A và SingletonA của bạn đều y chang nhau. Khác nhau ở chỗ:&lt;br&gt;
 - class A không thread-safe, còn SingletonA ở trên nhờ lock và volatile sẽ thread-safe.&lt;br&gt;
 - A.Method(): là class's static method =&amp;gt; accessible to any one.&lt;br&gt;
SingletonA.Instance.Method(): là instance's method =&amp;gt; accessible to
only the instance itself. Nhưng vì instance của bạn là static nên tất
nhiên cũng accessible to any one nốt.&lt;br&gt;
&lt;br&gt;
Nếu bạn lo lắng về chuyện nên static method hay static instance,
non-static method thì tùy theo yêu cầu cụ thể của bạn thôi, đừng bận
tâm về bộ nhớ, mình chả thấy khác gì mấy cả. Chỉ khác ở chỗ cái nào sử
dụng tiện hơn, cái nào cần initalize thế thôi.&lt;br&gt;</description>
<publisher>Vietnam .NET Community</publisher>
<language>vi-VN</language>
<managingEditor>automail-noreply@dot.net.vn</managingEditor>
<webMaster>automail-noreply@dot.net.vn</webMaster>
<copyright>Copyright 2005-2008 Vietnam .NET Community</copyright>
<pubDate>Mon, 18 Aug 2008 09:08:38 GMT</pubDate>
<category>Căn bản về .NET Framework</category>
<ttl>60</ttl>
<docs>http://cyber.law.harvard.edu/rss/rss.html</docs>
<generator>VIE Portal RSS Generator - Version 5.5.3057.24265 - http://www.vieportal.vn/</generator>
<item>
<title>Trả lời của 'Netnomad'</title>
<link>http://dot.net.vn/Desktop.aspx/Threads/CanBan-dotNET-Framework/Giai_phong_bo_nho/</link>
<description>thanks</description>
<author>automail-noreply@dot.net.vn</author>
<pubDate>Thu, 19 Jun 2008 18:26:26 GMT</pubDate>
<source>http://dot.net.vn/Desktop.aspx/Threads/CanBan-dotNET-Framework/Giai_phong_bo_nho/</source>
<category>Căn bản về .NET Framework</category>
</item>
<item>
<title>Trả lời của 'Hell Manager'</title>
<link>http://dot.net.vn/Desktop.aspx/Threads/CanBan-dotNET-Framework/Giai_phong_bo_nho/</link>
<description>Thứ 1 :Trong C# không giống như Delphi hay C++ là không có Pointer. Mà thằng BDS2006 và CodeGear2007 thì đang thực hiện điều này : bỏ Pointer.&lt;br&gt;&lt;br&gt;Thứ 2 : Cách giải phóng vùng nhớ của .NET là nếu bạn không còn dùng nữa(Ngoài Scope)  cộng với bạn không có dã tâm cố ý hủy bỏ nó thì nó sẽ tự hủy.&lt;br&gt;&lt;br&gt;Thứ 3: Không cần quan tâm đến từ khóa khai báo. Việc xác định từ khóa khai báo chỉ nhằm đóng gói Object và tiện cho việc tri xuất đúng đắng thôi, không có ý nghĩa gì với việc dọn rác cả.&lt;br&gt;&lt;br&gt; </description>
<author>automail-noreply@dot.net.vn</author>
<pubDate>Fri, 01 Aug 2008 18:17:45 GMT</pubDate>
<source>http://dot.net.vn/Desktop.aspx/Threads/CanBan-dotNET-Framework/Giai_phong_bo_nho/</source>
<category>Căn bản về .NET Framework</category>
</item>
<item>
<title>Trả lời của 'Nông Tiến Bắc'</title>
<link>http://dot.net.vn/Desktop.aspx/Threads/CanBan-dotNET-Framework/Giai_phong_bo_nho/</link>
<description>Bạn nói ko có Pointer là sai. Trong C# Reference Type chính là Pointer đó!</description>
<author>automail-noreply@dot.net.vn</author>
<pubDate>Mon, 18 Aug 2008 09:08:38 GMT</pubDate>
<source>http://dot.net.vn/Desktop.aspx/Threads/CanBan-dotNET-Framework/Giai_phong_bo_nho/</source>
<category>Căn bản về .NET Framework</category>
</item>
</channel>
</rss>