国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
c#多線程同步[MethodImpl(MethodImplOptions.Synchronized)]、lock(this)與lock(typeof(...))

[原創(chuàng)][MethodImpl(MethodImplOptions.Synchronized)]、lock(this)與lock(typeof(...))

 

 

 

對于稍微有點經(jīng)驗的.NET開發(fā)人員來說,倘若被問及如何保持線程同步,我想很多人都能說好好幾種。在眾多的線程同步的可選方式中,加鎖無疑是最為常用的。如果僅僅是基于方法級別的線程同步,使用System.Runtime.CompilerServices.MethodImplAttribute無疑是最為簡潔的一種方式。MethodImplAttribute可以用于instance method,也可以用于static method。當在某個方法上標注了MethodImplAttribute,并指定MethodImplOptions.Synchronized參數(shù),可以確保在不同線程中運行的該方式以同步的方式運行。我們幾天來討論MethodImplAttribute(MethodImplOptions.Synchronized)和lock的關系。

一、提出結論

在進行討論之前,我先提出下面3個結論:

1、[MethodImplAttribute(MethodImplOptions.Synchronized)]仍然采用加鎖的機制實現(xiàn)線程的同步。

2、如果[MethodImplAttribute(MethodImplOptions.Synchronized)]被應用到instance method,相當于對當前實例加鎖。

3、如果[MethodImplAttribute(MethodImplOptions.Synchronized)]被應用到static method,相當于當前類型加鎖

二、基于instance method的線程同步

為了驗證我們上面提出的結論,我作了一個小小的例子。在一個console application中定義了一個class:SyncHelper,其中定義了一個方法Execute。打印出方法執(zhí)行的時間,并休眠當前線程模擬一個耗時的操作:

class SyncHelper
{
    public void Execute()
    {
        Console.WriteLine("Excute at {0}", DateTime.Now);
        Thread.Sleep(5000);
    }
}

在入口Main方法中,創(chuàng)建SyncHelper對象,通過一個System.Threading.Timer對象實現(xiàn)每隔1s調用該對象的Execute方法:

class Program
{
    static void Main(string[] args)
    {
        SyncHelper helper = new SyncHelper();
        Timer timer = new Timer(
        delegate
        {
            helper.Execute();
        }, null, 0, 1000);

        Console.Read();

    }
}

 

 

 

 

 

 

 

 

 

由于Timer對象采用異步的方式進行調用,所以雖然Execute方法的執(zhí)行時間是5s,但是該方法仍然是每隔1s被執(zhí)行一次。這一點從最終執(zhí)行的結果可以看出:

為了讓同一個SyncHelper對象的Execute方法同步執(zhí)行,我們在Execute方法上添加了如下一個MethodImplAttribute:

[MethodImpl(MethodImplOptions.Synchronized)]
public void Execute()
{
    Console.WriteLine("Excute at {0}", DateTime.Now);
    Thread.Sleep(5000);
}

 

 

 

從如下的輸出結果我們可以看出Execute方法是以同步的方式執(zhí)行的,因為兩次執(zhí)行的間隔正式Execute方法執(zhí)行的時間:

在一開始我們提出的結論中,我們提到“如果[MethodImplAttribute(MethodImplOptions.Synchronized)]被應用到instance method,相當于對當前實例加鎖”。說得直白一點:[MethodImplAttribute(MethodImplOptions.Synchronized)] = lock(this)。我們可以通過下面的實驗驗證這一點。為此,在SyncHelper中定義了一個方法LockMyself。在此方法中對自身加鎖,并持續(xù)5s中,并答應加鎖和解鎖的時間。

public void LockMyself()
{
   lock (this)
    {
        Console.WriteLine("Lock myself at {0}", DateTime.Now);
        Thread.Sleep(5000);
        Console.WriteLine("Unlock myself at {0}", DateTime.Now);
    }
}

我們在Main()中以異步的方式(通過創(chuàng)建新的線程的方式)調用該方法:

static void Main(string[] args)
{
    SyncHelper helper = new SyncHelper();

    Thread thread = new Thread(
        delegate()
        {           

             helper.LockMyself();

        });
    thread.Start();
    Timer timer = new Timer(
    delegate
    {
        helper.Execute();
    }, null, 0, 1000);

    Console.Read();
}

 

 

 

 

 

 

結合我們的第二個結論想想最終的輸出會是如何。由于LockMyself方法是在另一個線程中執(zhí)行,我們可以簡單講該方法的執(zhí)行和Execute的第一個次執(zhí)行看作是同時的。但是MethodImplAttribute(MethodImplOptions.Synchronized)]果真是通過lock(this)的方式實現(xiàn)的話,Execute必須在等待LockMyself方法執(zhí)行結束將對自身的鎖釋放后才能得以執(zhí)行。也就是說LockMyself和第一次Execute方法的執(zhí)行應該相差5s。而輸出的結果證實了這點:

三、基于static method的線程同步

討論完再instance method上添加MethodImplAttribute(MethodImplOptions.Synchronized)]的情況,我們相同的方式來討論倘若一樣的MethodImplAttribute被應用到static方法,又會使怎樣的結果。

我們先將Execute方法上的MethodImplAttribute注釋掉,并將其改為static方法:

//[MethodImpl(MethodImplOptions.Synchronized)]
public static void Execute()
{
    Console.WriteLine("Excute at {0}", DateTime.Now);
    Thread.Sleep(5000);
}

 

 

 

 

 

 

 

 

在Main方法中,通過Timer調用該static方法:

static void Main(string[] args)
{
    Timer timer = new Timer(
    delegate
    {
        SyncHelper.Execute();
    }, null, 0, 1000);

    Console.Read();
}

毫無疑問,Execute方法將以1s的間隔異步地執(zhí)行,最終的輸出結果如下:

然后我們將對[MethodImpl(MethodImplOptions.Synchronized)]的注釋取消:

[MethodImpl(MethodImplOptions.Synchronized)]
public static void Execute()
{
    Console.WriteLine("Excute at {0}", DateTime.Now);
    Thread.Sleep(5000);
}

最終的輸出結果證實了Execute將會按照我們期望的那樣以同步的方式執(zhí)行,執(zhí)行的間隔正是方法執(zhí)行的時間:

我們回顧一下第三個結論:“如果[MethodImplAttribute(MethodImplOptions.Synchronized)]被應用到static method,相當于當前類型加鎖”。為了驗證這個結論,在SyncHelper中添加了一個新的static方法:LockType。該方法對SyncHelper tpye加鎖,并持續(xù)5s中,在加鎖和解鎖是打印出當前時間:

public static void LockType()
{
    lock (typeof(SyncHelper))
    {
        Console.WriteLine("Lock SyncHelper type at {0}", DateTime.Now);
        Thread.Sleep(5000);
        Console.WriteLine("Unlock SyncHelper type at {0}", DateTime.Now);
    }
}

在Main中,像驗證instance method一樣,創(chuàng)建新的線程執(zhí)行LockType方法:

static void Main(string[] args)
{
    Thread thread = new Thread(
        delegate()
        {
            SyncHelper.LockType();
        });
    thread.Start();

    Timer timer = new Timer(
    delegate
    {
        SyncHelper.Execute();
    }, null, 0, 1000);

    Console.Read();
}

如果基于static method的[MethodImplAttribute(MethodImplOptions.Synchronized)]是通過對Type進行加鎖實現(xiàn)。那么通過Timer輪詢的第一個Execute方法需要在LockType方法執(zhí)行完成將對SyncHelper type的鎖釋放后才能執(zhí)行。所以如果上述的結論成立,將會有下面的輸出:

四、總結

對于加鎖來說,鎖的粒度的選擇顯得至關重要。在不同的場景中需要選擇不同粒度的鎖。如果選擇錯誤往往會對性能造成很到的影響,嚴重時還會引起死鎖。就拿[MethodImplAttribute(MethodImplOptions.Synchronized)]來說,如果開發(fā)人員對它的實現(xiàn)機制不了解,很有可能使它lock(this)或者lock(typeof(…))并存,造成方法得不到及時地執(zhí)行。

最后說一句題外話,因為字符串駐留機制的存在,切忌對string進行加鎖。

本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
定時器
計時器
java常用的關鍵字
5.3.7 單例模式的優(yōu)缺點
Java多線程編程-(1)-線程安全和鎖Synchronized概念
Java設計模式 之 Singleton
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服