繁体   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