簡體   English   中英

線程鎖定與創建新對象

[英]Thread locking vs creating a new object

C#lock語句一次僅允許一個線程訪問一個對象。 在Parallel.ForEach循環中,在循環中創建一個新的對象(局部變量)比使用字段變量要快,因為那樣就不會阻塞線程嗎? 每種方式的利弊是什么?

我正在使用下面的代碼,似乎創建本地var而不是在字段上使用鎖稍微快一些。

nb。 toEmails變量中有3個電子郵件字符串。

//Method 1 with lock statement takes 14092ms
List<string> toEmails = getListOfToEmails();
Object locker = new object();
SmtpClient smtpClient = getSmtpObject();//smtpClient is used here as a field
Parallel.ForEach(toEmails, toEmail =>
{
    string emailBody = getEmailBody(toEmail);

    MailMessage mailMessage = getMailMesssageObject(emailBody, toEmail);

    lock (locker)
    {
        smtpClient.Send(mailMessage);
    }
});

//Method 2 without lock statement (creating a new local var each iteration) takes 13947ms
List<string> toEmails = getListOfToEmails();
Parallel.ForEach(toEmails, toEmail =>
{
    SmtpClient smtpClient = getSmtpObject();//smtpClient is used here as a local var

    string emailBody = getEmailBody(toEmail);

    MailMessage mailMessage = getMailMesssageObject(emailBody, toEmail);

    smtpClient.Send(mailMessage);
});

使用此ForEach重載:

Parallel.ForEach(toEmails, () => getSmtpObject() , (toEmail, state, smtp) =>
{
    SmtpClient smtpClient = smtp;

    string emailBody = getEmailBody(toEmail);

    MailMessage mailMessage = getMailMesssageObject(emailBody, toEmail);

    smtpClient.Send(mailMessage);

    return smtp;
}, smtp => {});

第二個參數是一個委托,您可以使用它來創建線程本地數據。 在循環的每個迭代中,您將獲取本地數據,您可以對其進行更改並返回到下一個迭代。

最后一個參數是另一個委托,它將在每個任務結束時調用

如果存在共享資源,則在“簡單鎖定”中更可取。 正如您的情況一樣,將SMTP CLIENT用作共享資源非常簡單。 因此,如果您每次創建新對象,它都是非常安全的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM