在同步块内部和外部使用字段是否安全?
Is it safe to use field inside and outside synchronized block?
背景
我们的应用程序发送在数据库中排队的电子邮件 table。我们遇到过一些重复发送电子邮件的情况,因此我正在实施锁定以防止多个线程同时发送电子邮件。
ReSharper 警告我:
the field is sometimes used inside synchronized block and sometimes
used without synchronization
问题
为什么 ReSharper 告诉我这个,我为什么会担心它?
代码
这是我的(删节)代码:
private readonly IMailQueueRepository _mailQueueRepository = new MailQueueRepository();
private static object _messageQueueLock = new object();
public void SendAllQueuedMessages(IPrincipal caller)
{
lock (_messageQueueLock) // Prevent concurrent callers
{
var message = _mailQueueRepository.GetUnsentMessage();
while (message != null)
{
SendQueuedMessage(message);
message = _mailQueueRepository.GetUnsentMessage();
}
}
}
public void SendQueuedMessage(IMessage message)
{
// I get the ReSharper warning here on _mailQueueRepository
var messageAttachments = _mailQueueRepository.GetMessageAttachments(message.Id);
// etc.
}
ReSharper 无法告诉(或保证)SendQueuedMessage()
仅从同步块内调用。所以就它而言,其他代码可能会在没有同步的情况下调用 SendQueuedMessage()
,并且 _mailQueueRepository
正在 SendQueuedMessage()
.
中使用
如果您确定没有其他代码(包含 class 的内部或外部)调用此方法,或者您已确定所有从 class 到 [=10= 的调用] 也同步 使用相同的锁对象 ,你没问题。如果您的 class 之外没有其他代码实际需要此方法,我建议您将其设为私有。
问题场景:
We've had some instances of duplicate emails being sent, so I'm implementing a lock to prevent multiple threads from sending emails simultaneously.
因此您正在使用 Lock()
来防止这种情况发生,这意味着您需要同步访问公共资源的线程,在本例中为 _mailQueueRepository
但是在相同的代码中你再次使用 _mailQueueRepository
而没有 Lock
// I get the ReSharper warning here on _mailQueueRepository
var messageAttachments = _mailQueueRepository.GetMessageAttachments(message.Id); // <== Accessed without a lock
所以这是一个警告,告诉您宝贵的资源以两种不同的形式被访问:一种是 synchronized
(线程安全),另一种是 non-synchronized
(非线程安全)。
这是一个警告,让 你 知道(或让你识别)这种矛盾的资源使用可能引起的问题_mailQueueRepository
。您可以选择完全使用 _mailQueueRepository
synchronized
(与 lock
一起使用,警告将消失)或设法不 运行 竞争条件。
此外,您可能会考虑以这样一种方式重新构建代码,以便使用从 _mailQueueRepository
中提取的参数调用您的 SendQueuedMessage()
,避免混合使用。
背景
我们的应用程序发送在数据库中排队的电子邮件 table。我们遇到过一些重复发送电子邮件的情况,因此我正在实施锁定以防止多个线程同时发送电子邮件。
ReSharper 警告我:
the field is sometimes used inside synchronized block and sometimes used without synchronization
问题
为什么 ReSharper 告诉我这个,我为什么会担心它?
代码
这是我的(删节)代码:
private readonly IMailQueueRepository _mailQueueRepository = new MailQueueRepository();
private static object _messageQueueLock = new object();
public void SendAllQueuedMessages(IPrincipal caller)
{
lock (_messageQueueLock) // Prevent concurrent callers
{
var message = _mailQueueRepository.GetUnsentMessage();
while (message != null)
{
SendQueuedMessage(message);
message = _mailQueueRepository.GetUnsentMessage();
}
}
}
public void SendQueuedMessage(IMessage message)
{
// I get the ReSharper warning here on _mailQueueRepository
var messageAttachments = _mailQueueRepository.GetMessageAttachments(message.Id);
// etc.
}
ReSharper 无法告诉(或保证)SendQueuedMessage()
仅从同步块内调用。所以就它而言,其他代码可能会在没有同步的情况下调用 SendQueuedMessage()
,并且 _mailQueueRepository
正在 SendQueuedMessage()
.
如果您确定没有其他代码(包含 class 的内部或外部)调用此方法,或者您已确定所有从 class 到 [=10= 的调用] 也同步 使用相同的锁对象 ,你没问题。如果您的 class 之外没有其他代码实际需要此方法,我建议您将其设为私有。
问题场景:
We've had some instances of duplicate emails being sent, so I'm implementing a lock to prevent multiple threads from sending emails simultaneously.
因此您正在使用 Lock()
来防止这种情况发生,这意味着您需要同步访问公共资源的线程,在本例中为 _mailQueueRepository
但是在相同的代码中你再次使用 _mailQueueRepository
而没有 Lock
// I get the ReSharper warning here on _mailQueueRepository
var messageAttachments = _mailQueueRepository.GetMessageAttachments(message.Id); // <== Accessed without a lock
所以这是一个警告,告诉您宝贵的资源以两种不同的形式被访问:一种是 synchronized
(线程安全),另一种是 non-synchronized
(非线程安全)。
这是一个警告,让 你 知道(或让你识别)这种矛盾的资源使用可能引起的问题_mailQueueRepository
。您可以选择完全使用 _mailQueueRepository
synchronized
(与 lock
一起使用,警告将消失)或设法不 运行 竞争条件。
此外,您可能会考虑以这样一种方式重新构建代码,以便使用从 _mailQueueRepository
中提取的参数调用您的 SendQueuedMessage()
,避免混合使用。