简体   繁体   English

线程锁定与创建新对象

[英]Thread locking vs creating a new object

The C# lock statement allows only one thread to access an object at a time. C#lock语句一次仅允许一个线程访问一个对象。 In a Parallel.ForEach loop, wouldn't it be faster to create a new object (local variable) within the loop, rather than using a field variable, since that way no threads are ever blocked? 在Parallel.ForEach循环中,在循环中创建一个新的对象(局部变量)比使用字段变量要快,因为那样就不会阻塞线程吗? What would be the pros/cons of each way? 每种方式的利弊是什么?

I am using the code below, it seems that creating a local var instead of using a lock on a field is slightly faster. 我正在使用下面的代码,似乎创建本地var而不是在字段上使用锁稍微快一些。

nb. nb。 There are 3 email strings in the toEmails variable. 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);
});

Use this overload of ForEach : 使用此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 => {});

Second argument is a delegate that you can use it to create thread local data. 第二个参数是一个委托,您可以使用它来创建线程本地数据。 in each iteration of loop you will get local data and you can change it and return to next iteration. 在循环的每个迭代中,您将获取本地数据,您可以对其进行更改并返回到下一个迭代。

Last argument is another delegate this will be called in end of every task 最后一个参数是另一个委托,它将在每个任务结束时调用

In Simple lock is preferable when there is a shared resource. 如果存在共享资源,则在“简单锁定”中更可取。 As in your case its quite simple that SMTP CLIENT is not used as a shared resource. 正如您的情况一样,将SMTP CLIENT用作共享资源非常简单。 so its quite safe if you create new object each time. 因此,如果您每次创建新对象,它都是非常安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM