C #: датируемые вопросы безопасности потоков - PullRequest
3 голосов
/ 15 мая 2011

У меня есть одноэлементный объект под названием DataStorage, который хранит общие данные в моем приложении;одним из них является Datatable, называемый myTable, который будет читаться и записываться несколькими потоками.У меня есть закрытый объект, который будет использоваться в качестве блокировки в DataStorage, т. Е.

private object lockObj = new object();

Я заблокировал доступ к myTable следующим образом:

private DataTable myTable;
public DataTable MyTable
{
    get
    { lock(lockObj) { return myTable; } }
    set
    { lock(lockObj) { myTable = value; } }
}

Другой объект, т.е. MyObj, получит этот объект данных, сделайте на нем Select, а затем измените некоторое значение в извлеченной DataRow [] из Select.Я читал, что Select не является потокобезопасным, поэтому я написал свой код следующим образом:

// lock on MyTable
DataTable dt = DataStorage.Instance.MyTable;

lock (MyObjLockObj)  // lock object for MyObj class
{
    // do a select, then modify value in the returned row
    DataRow[] foundRows = dt.Select("some expression");
    foundRows[0]["some col"] = 123456;
}

Вопросы: 1. В целом, является ли этот код потокобезопасным?

  1. Когда я изменяю извлеченный DataRow в MyObj, обеспечивает ли установщик MyTable его безопасность потока?Поскольку установщик предназначен для установки DataTable, а не DataRow.

  2. Должен ли я переместить код, обращающийся к DataStorage.Instance.MyTable, в тот же блок блокировки, что и Select?

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 15 мая 2011

Эти блокировки в геттере и сеттере совершенно бесполезны.Операция «myTable = значение» уже атомарна, ее не нужно заключать в блокировку.И эта блокировка, конечно же, не имеет ничего общего с изменением строк.Однако эта блокировка (MyObjLockObj) гарантирует, что один и только один поток получит доступ к вашей таблице данных, если в вашем приложении используется тот же MyObjLockObj.Если вы используете этот набор данных нечасто, это не будет проблемой, однако, если ваше приложение полностью связано с этим набором данных, у вас возникнут проблемы с производительностью.в многопоточном приложении это плохое решение.Если вы читаете данные для этого набора данных из БД, вы должны прочитать один набор данных для каждого потока, изменить его строки и зафиксировать изменения обратно в БД.

1 голос
/ 15 мая 2011

ваш код не является потокобезопасным, потому что:

блокировка свойства только гарантирует, что один поток не может использовать свойство get / set одновременно, но после того, как они получат доступ, они могут изменить его одновременно.

т.е.

поток может использовать свойство MyTable, чтобы получить доступ к данным. после этого другой thred может использовать свойство для получения того же экземпляра. затем, после того как они оба получат доступ к myTable, они оба смогут писать в него напрямую без синхронизации

так что перемещение аксессора в замок тоже не поможет.

Лучше предоставить методы, которые изменяют данные и выполняют синхронизацию в этих методах, а не предоставляют доступ к данным напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...