gpt4 book ai didi

c# - 锁定线程安全设备 IO 的单例类?

转载 作者:太空宇宙 更新时间:2023-11-03 10:25:29 25 4
gpt4 key购买 nike

假设我有单例类 Singleton,它可以读取和写入 SerialPort

public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());

public static Singleton Instance { get { return lazy.Value; } }

SerialPort commPort = new SerialPort();

private Singleton()
{
// Setup SerialPort
}

public String Read()
{
return commPort.ReadLine();
}

public void Write(String cmd)
{
commPort.WriteLine(cmd);
}
}

现在还可以说我有多个线程访问 SerialPort 末尾的设备。有些线程可能只写入 SerialPort,有些线程可能写入然后从 SerialPort 读取。

我想确保当一个线程正在读然后写时它不会被另一个线程中断。这样做的方法是 lock Singleton.Instance 本身吗?

// Running on thread 1
public Boolean SetLEDStatus(int onOff)
{
lock(Singleton.Instance)
{
Singleton.Instance.Write("SET LED " + onOff.ToString() + "\r\n");
String status = Singleton.Instance.ReadLine();
return (status.Contains("SUCCESS")) ? true : false;
}
}

// Running on thread 2
public Boolean IsLEDOn()
{
lock(Singleton.Instance)
{
Singleton.Instance.Write("GET LED\r\n");
return (Singleton.Instance.ReadLine().Contains("ON")) ? true : false;
}
}

在这种情况下,如果 SetLEDStatusIsLEDOn 被调用的时间非常接近,我想确保 SerialPort 是在阅读之前不要写太多。我使用锁定会阻止这种情况吗?

这种类型的操作是否称为“事务性 IO”?

如果这确实是正确的,是否还有其他更有效的方法来执行相同类型的操作?

编辑:

我理解为什么锁定 Singleton.Instance 可能不好,如果要锁定 Singleton.Instance 然后调用 Singleton 中的方法。 Instance 也试图锁定自己,就会出现死锁。

本来打算在单例中使用私有(private)对象来加锁。但由于下面概述的情况,我有点说服自己放弃了。其中,我不确定这是否正确。

(使用上述两种方法(减少锁定)在 Thread1 和 Thread2 上运行)

  1. Thread1 调用WriteSingleton.Instance
  2. Thread2 调用了Write,但是被锁阻塞了
  3. Singleton.Instance完成Write并释放锁
  4. Thread2 调用Write 执行,Singleton.Instance 锁定
  5. Thread1 调用Read,但被锁阻塞
  6. Singleton.Instance完成Write并释放锁
  7. Thread1s Read 执行,Singleton.Instance
  8. Thread2 调用Read,但被锁阻塞
  9. Singleton.Instance 完成读取并释放锁
  10. Thread2sRead被执行,Singleton.Instance
  11. Singleton.Instance 完成读取并释放锁

在这种情况下,连续有两次 Writes 到串行端口,这是不正确的。对于某些类型的通信,我需要能够背靠背地执行 Write Read

最佳答案

对于锁对象,我会在类上使用私有(private)字段(即非静态)而不是单例实例本身,使用same reasoning on why not to lock(this) ever .

我通常使用这样的声明,因为声明锁对象作为自文档化代码更具可读性。

private readonly object _LEDLock = new object();

这样,当其他人去看时,他们会说“哦,这是保护线程访问 LED 资源的锁对象。”

恕我直言,我认为 SetLEDStatusIsLEDOn 方法(带锁定)中的行为最好封装在您的 Singleton 类中,如下所示:

public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());

public static Singleton Instance { get { return lazy.Value; } }

SerialPort commPort = new SerialPort();

private readonly object _LEDLock = new object();

private Singleton()
{
// Setup SerialPort
}

/// <summary>
/// This goes in the singleton class, because this is the class actually doing the work.
/// The behavior belongs in this class. Now it can be called with thread-safety from
/// any number of threads
/// </summary>
public Boolean SetLEDStatus(int onOff)
{
lock(_LEDLock)
{
var cmd = "SET LED " + onOff.ToString() + "\r\n";
commPort.WriteLine(cmd);
string status = commPort.ReadLine();
return (status.Contains("SUCCESS")) ? true : false;
}
}

public Boolean IsLEDOn()
{
lock(_LEDLock)
{
commPort.Write("GET LED\r\n");
var result = commPort.ReadLine().Contains("ON")) ? true : false;
return result;
}
}
}

现在,任何调用线程都可以以线程安全的方式调用这些方法。

关于c# - 锁定线程安全设备 IO 的单例类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31731593/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com